-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
496 lines (424 loc) · 509 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[pangyalin的博客]]></title>
<subtitle><![CDATA[pangyalin的博客]]></subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://www.iwooto.com/"/>
<updated>2016-06-05T15:10:43.897Z</updated>
<id>http://www.iwooto.com/</id>
<author>
<name><![CDATA[pangyalin]]></name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title><![CDATA[sqlserver触发器]]></title>
<link href="http://www.iwooto.com/2016/06/05/sqlserver%E8%A7%A6%E5%8F%91%E5%99%A8/"/>
<id>http://www.iwooto.com/2016/06/05/sqlserver触发器/</id>
<published>2016-06-05T14:23:01.000Z</published>
<updated>2016-06-05T15:10:43.897Z</updated>
<content type="html"><![CDATA[<p>触发器的分类<br>DML触发器是响应Insert、Update、Delete语句,DDL是响应Create、Alter、Drop开头的数据定义语句而激活的。<br>1.触发器的概念:就是在数据库进行insert、delete、update时会触发我们规定的的一系列的动作<br>创建一个简单的触发器<a id="more"></a><br><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">create trigger tgr_name --触发器的名称</span><br><span class="line">on table_name --触发器作用的表名</span><br><span class="line"> <span class="keyword">for</span> insert --触发的操作</span><br><span class="line">as</span><br><span class="line"> <span class="built_in">print</span> <span class="string">'我添加了一条记录哦'</span></span><br><span class="line">go</span><br></pre></td></tr></table></figure></p>
<p>2.获取触发器触发是操作的数据<br>触发器有两个特殊的表,新插入的数据表(inserted)和删除的数据表(deleted),这两张表只能读去数据,不能修改数据。inserted表存放插入和修改后的数据,deleted表存放删除和修改前的数据。<br><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">create trigger OrderDetail_Update</span><br><span class="line"> on OrderDetail</span><br><span class="line"> after update</span><br><span class="line">as</span><br><span class="line">begin</span><br><span class="line"> <span class="keyword">if</span>(update(je))--列级触发器,当金额改变时触发</span><br><span class="line"> insert into OrderDetailTz select newid() id,* from deleted --获取插入前的数据插入到调整表当中</span><br><span class="line">end</span><br></pre></td></tr></table></figure></p>
<p>3.After 与Instead Of<br>Instead Of触发器与After触发器的工作流程是不一样。<br>After触发器是在SQLSERVER服务器接到执行SQL语句请求之后,先建立Inserted和Updated临时表,然后在更改物理表上的数据,最后才激活触发器程序。<br>而Instead Of触发器在SQLSERVER服务器接到执行SQL语句请求,建立Inserted和Updated临时表后就激活了Instead Of触发器程序,至于SQL语句的请求如何操作数据就不在管了,把执行权全权叫给了Instead Of触发器。<br>Instead Of触发器实例<br><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">Create Trigger OrderDetail_Insert</span><br><span class="line"> ON OrderDetail</span><br><span class="line"> Instead Of Insert</span><br><span class="line">AS</span><br><span class="line">Begin</span><br><span class="line"> Set Nocount On; /*屏蔽触发器里Insert语句执行完后返回的所影响的行数的消息*/</span><br><span class="line"> Declare @Orderid int,@Price money,@discount real</span><br><span class="line"> select @OrderId=OrderId,@Price=Price,@Discount=Discount from Inserted</span><br><span class="line"> <span class="keyword">if</span>(@Discount)><span class="number">0.6</span></span><br><span class="line"> begin</span><br><span class="line"> <span class="built_in">print</span> <span class="string">'折扣不能大于0.6'</span></span><br><span class="line"> end</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> begin</span><br><span class="line"> insert into OrderDetail(OrderId,Price,Discount) values(@OrderId,@Price,@discount)</span><br><span class="line"> end</span><br><span class="line">End</span><br></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<![CDATA[<p>触发器的分类<br>DML触发器是响应Insert、Update、Delete语句,DDL是响应Create、Alter、Drop开头的数据定义语句而激活的。<br>1.触发器的概念:就是在数据库进行insert、delete、update时会触发我们规定的的一系列的动作<br>创建一个简单的触发器]]>
</summary>
<category term="sqlserver" scheme="http://www.iwooto.com/tags/sqlserver/"/>
</entry>
<entry>
<title><![CDATA[java自定义注解]]></title>
<link href="http://www.iwooto.com/2016/04/19/java%E6%B3%A8%E8%A7%A3/"/>
<id>http://www.iwooto.com/2016/04/19/java注解/</id>
<published>2016-04-19T12:31:10.000Z</published>
<updated>2016-05-24T14:10:38.583Z</updated>
<content type="html"><![CDATA[<h1 id="u5143_u6CE8_u89E3"><a href="#u5143_u6CE8_u89E3" class="headerlink" title="元注解"></a>元注解</h1><p>@Target表示该注解可以用于什么地方,可能的ElementType参数有:<br>CONSTRUCTOR:构造器的声明<br>FIELD:域声明(包括enum实例)<br>LOCAL_VARIABLE:局部变量声明<br>METHOD:方法声明<br>PACKAGE:包声明<br>PARAMETER:参数声明<br>TYPE:类、接口(包括注解类型)或enum声明</p>
<p>@Retention表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:<br>SOURCE:在源文件中有效(即源文件保留)注解将被编译器丢弃<br>CLASS:注解在class文件中可用,但会被VM丢弃<br>RUNTIME:VM将在运行期间保留注解,因此可以通过反射机制读取注解的信息。</p>
<p>@Document 将注解包含在Javadoc中</p>
<p>@Inherited 允许子类继承父类中的注解<br> @Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。</p>
<p> 注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。</p>
<p> 当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。</p>
<h1 id="u81EA_u5B9A_u4E49_u6CE8_u89E3"><a href="#u81EA_u5B9A_u4E49_u6CE8_u89E3" class="headerlink" title="自定义注解"></a>自定义注解</h1><p> 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。<br>定义注解格式:<br> public @interface 注解名 {定义体}</p>
<p>注解参数的可支持数据类型:</p>
<p> 1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)<br> 2.String类型<br> 3.Class类型<br> 4.enum类型<br> 5.Annotation类型<br> 6.以上所有类型的数组</p>
<p> Annotation类型里面的参数该怎么设定:<br> 第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型; <br> 第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String; <br> 第三,如果只有一个参数成员,最好把参数名称设为”value”,后加小括号.例:下面的例子FruitName注解就只有一个参数成员。</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">package annotation;</span><br><span class="line"></span><br><span class="line">import java.lang.annotation.Documented;</span><br><span class="line">import java.lang.annotation.ElementType;</span><br><span class="line">import java.lang.annotation.Retention;</span><br><span class="line">import java.lang.annotation.RetentionPolicy;</span><br><span class="line">import java.lang.annotation.Target;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 水果名称注解</span><br><span class="line"> * @author peida</span><br><span class="line"> *</span><br><span class="line"> */</span><br><span class="line">@Target(ElementType.FIELD)</span><br><span class="line">@Retention(RetentionPolicy.RUNTIME)</span><br><span class="line">@Documented</span><br><span class="line">public @interface FruitName {</span><br><span class="line"> String value() default <span class="string">""</span>;</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><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><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">package annotation;</span><br><span class="line"></span><br><span class="line">import java.lang.annotation.Documented;</span><br><span class="line">import java.lang.annotation.ElementType;</span><br><span class="line">import java.lang.annotation.Retention;</span><br><span class="line">import java.lang.annotation.RetentionPolicy;</span><br><span class="line">import java.lang.annotation.Target;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 水果颜色注解</span><br><span class="line"> * @author peida</span><br><span class="line"> *</span><br><span class="line"> */</span><br><span class="line">@Target(ElementType.FIELD)</span><br><span class="line">@Retention(RetentionPolicy.RUNTIME)</span><br><span class="line">@Documented</span><br><span class="line">public @interface FruitColor {</span><br><span class="line"> /**</span><br><span class="line"> * 颜色枚举</span><br><span class="line"> * @author peida</span><br><span class="line"> *</span><br><span class="line"> */</span><br><span class="line"> public enum Color{ BULE,RED,GREEN};</span><br><span class="line"> </span><br><span class="line"> /**</span><br><span class="line"> * 颜色属性</span><br><span class="line"> * @<span class="built_in">return</span></span><br><span class="line"> */</span><br><span class="line"> Color fruitColor() default Color.GREEN;</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 校验颜色</span><br><span class="line"> * @<span class="built_in">return</span></span><br><span class="line"> */</span><br><span class="line"> public Valid valid default @Valid;</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"> @Target(ElementType.FIELD)</span><br><span class="line"> @Retention(RetentionPolicy.RUNTIME)</span><br><span class="line"> @Documented</span><br><span class="line"> public @interface Valid {</span><br><span class="line"> </span><br><span class="line"> /**</span><br><span class="line"> * 必须与<span class="keyword">in</span>中String相符,目前仅支持String类型</span><br><span class="line"> * </span><br><span class="line"> * @<span class="built_in">return</span> e.g. {<span class="string">"abc"</span>,<span class="string">"123"</span>}</span><br><span class="line"> */</span><br><span class="line"> public String[] <span class="keyword">in</span>() default {};</span><br><span class="line"> /**</span><br><span class="line"> * 是否允许为空,用于验证数据 default <span class="literal">true</span></span><br><span class="line"> * </span><br><span class="line"> * @<span class="built_in">return</span></span><br><span class="line"> */</span><br><span class="line"> public boolean allowNull() default <span class="literal">true</span>;</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>/<strong><strong><em>*</em></strong></strong>注解使用<strong><strong><strong><em>*</em></strong></strong></strong>/<br><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">public class Fruit {</span><br><span class="line"> </span><br><span class="line"> @FruitName(<span class="string">"Apple"</span>)</span><br><span class="line"> private String fruitName;</span><br><span class="line"> </span><br><span class="line"> @FruitColor(fruitColor=Color.RED, valid =@Valid(allowNull = <span class="literal">false</span>))</span><br><span class="line"> private String fruitColor;</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>/<strong><strong><em>*</em></strong></strong>注解处理器<strong><strong><strong><em>*</em></strong></strong></strong>/<br><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></pre></td><td class="code"><pre><span class="line">public class Test {</span><br><span class="line"> public static void main(String[] args) throws IOException {</span><br><span class="line"> </span><br><span class="line"> String strFruitName=<span class="string">" 水果名称:"</span>;</span><br><span class="line"> String strFruitColor=<span class="string">" 水果颜色:"</span>;</span><br><span class="line"> Boolean bool = <span class="literal">true</span>;//是否校验</span><br><span class="line"> Field[] fields = Fruit.class.getDeclaredFields();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(Field field :fields){</span><br><span class="line"> <span class="keyword">if</span>(field.isAnnotationPresent(FruitName.class)){</span><br><span class="line"> FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);</span><br><span class="line"> strFruitName=strFruitName+fruitName.value();</span><br><span class="line"> System.out.println(strFruitName);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(field.isAnnotationPresent(FruitColor.class)){</span><br><span class="line"> FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);</span><br><span class="line"> strFruitColor=strFruitColor+fruitColor.fruitColor().toString();</span><br><span class="line"> bool = fruitColor.Valid.allowNull();</span><br><span class="line"> System.out.println(strFruitColor);</span><br><span class="line"> System.out.println(bool);</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>
]]></content>
<summary type="html">
<![CDATA[<h1 id="u5143_u6CE8_u89E3"><a href="#u5143_u6CE8_u89E3" class="headerlink" title="元注解"></a>元注解</h1><p>@Target表示该注解可以用于什么地方,可能的ElementType参数有]]>
</summary>
<category term="java" scheme="http://www.iwooto.com/tags/java/"/>
</entry>
<entry>
<title><![CDATA[python学习(1)]]></title>
<link href="http://www.iwooto.com/2016/04/06/python%E5%AD%A6%E4%B9%A0-1/"/>
<id>http://www.iwooto.com/2016/04/06/python学习-1/</id>
<published>2016-04-05T17:23:39.000Z</published>
<updated>2016-04-05T17:26:31.283Z</updated>
<content type="html"><![CDATA[<h1 id="Python_u5B66_u4E60_281_29"><a href="#Python_u5B66_u4E60_281_29" class="headerlink" title="Python学习(1)"></a>Python学习(1)</h1><a id="more"></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><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><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><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br><span class="line">554</span><br><span class="line">555</span><br><span class="line">556</span><br><span class="line">557</span><br><span class="line">558</span><br><span class="line">559</span><br><span class="line">560</span><br><span class="line">561</span><br><span class="line">562</span><br><span class="line">563</span><br><span class="line">564</span><br><span class="line">565</span><br><span class="line">566</span><br><span class="line">567</span><br><span class="line">568</span><br><span class="line">569</span><br><span class="line">570</span><br><span class="line">571</span><br><span class="line">572</span><br><span class="line">573</span><br><span class="line">574</span><br><span class="line">575</span><br><span class="line">576</span><br><span class="line">577</span><br><span class="line">578</span><br><span class="line">579</span><br><span class="line">580</span><br><span class="line">581</span><br><span class="line">582</span><br><span class="line">583</span><br><span class="line">584</span><br><span class="line">585</span><br><span class="line">586</span><br><span class="line">587</span><br><span class="line">588</span><br><span class="line">589</span><br><span class="line">590</span><br><span class="line">591</span><br><span class="line">592</span><br><span class="line">593</span><br><span class="line">594</span><br><span class="line">595</span><br><span class="line">596</span><br><span class="line">597</span><br><span class="line">598</span><br><span class="line">599</span><br><span class="line">600</span><br><span class="line">601</span><br><span class="line">602</span><br><span class="line">603</span><br><span class="line">604</span><br><span class="line">605</span><br><span class="line">606</span><br><span class="line">607</span><br><span class="line">608</span><br><span class="line">609</span><br><span class="line">610</span><br><span class="line">611</span><br><span class="line">612</span><br><span class="line">613</span><br><span class="line">614</span><br><span class="line">615</span><br><span class="line">616</span><br><span class="line">617</span><br><span class="line">618</span><br><span class="line">619</span><br><span class="line">620</span><br><span class="line">621</span><br><span class="line">622</span><br><span class="line">623</span><br><span class="line">624</span><br><span class="line">625</span><br><span class="line">626</span><br><span class="line">627</span><br><span class="line">628</span><br><span class="line">629</span><br><span class="line">630</span><br><span class="line">631</span><br><span class="line">632</span><br><span class="line">633</span><br><span class="line">634</span><br><span class="line">635</span><br><span class="line">636</span><br><span class="line">637</span><br><span class="line">638</span><br><span class="line">639</span><br><span class="line">640</span><br><span class="line">641</span><br><span class="line">642</span><br><span class="line">643</span><br><span class="line">644</span><br><span class="line">645</span><br><span class="line">646</span><br><span class="line">647</span><br><span class="line">648</span><br><span class="line">649</span><br><span class="line">650</span><br><span class="line">651</span><br><span class="line">652</span><br><span class="line">653</span><br><span class="line">654</span><br><span class="line">655</span><br><span class="line">656</span><br><span class="line">657</span><br><span class="line">658</span><br><span class="line">659</span><br><span class="line">660</span><br><span class="line">661</span><br><span class="line">662</span><br><span class="line">663</span><br><span class="line">664</span><br><span class="line">665</span><br><span class="line">666</span><br><span class="line">667</span><br><span class="line">668</span><br><span class="line">669</span><br><span class="line">670</span><br><span class="line">671</span><br><span class="line">672</span><br><span class="line">673</span><br><span class="line">674</span><br><span class="line">675</span><br><span class="line">676</span><br><span class="line">677</span><br><span class="line">678</span><br><span class="line">679</span><br><span class="line">680</span><br><span class="line">681</span><br><span class="line">682</span><br><span class="line">683</span><br><span class="line">684</span><br><span class="line">685</span><br><span class="line">686</span><br><span class="line">687</span><br><span class="line">688</span><br><span class="line">689</span><br><span class="line">690</span><br><span class="line">691</span><br><span class="line">692</span><br><span class="line">693</span><br><span class="line">694</span><br><span class="line">695</span><br><span class="line">696</span><br><span class="line">697</span><br><span class="line">698</span><br><span class="line">699</span><br><span class="line">700</span><br><span class="line">701</span><br><span class="line">702</span><br><span class="line">703</span><br><span class="line">704</span><br><span class="line">705</span><br><span class="line">706</span><br><span class="line">707</span><br><span class="line">708</span><br><span class="line">709</span><br><span class="line">710</span><br><span class="line">711</span><br><span class="line">712</span><br><span class="line">713</span><br><span class="line">714</span><br><span class="line">715</span><br><span class="line">716</span><br><span class="line">717</span><br><span class="line">718</span><br><span class="line">719</span><br><span class="line">720</span><br><span class="line">721</span><br><span class="line">722</span><br><span class="line">723</span><br><span class="line">724</span><br><span class="line">725</span><br><span class="line">726</span><br><span class="line">727</span><br><span class="line">728</span><br><span class="line">729</span><br><span class="line">730</span><br><span class="line">731</span><br><span class="line">732</span><br><span class="line">733</span><br><span class="line">734</span><br><span class="line">735</span><br><span class="line">736</span><br><span class="line">737</span><br><span class="line">738</span><br><span class="line">739</span><br><span class="line">740</span><br><span class="line">741</span><br><span class="line">742</span><br><span class="line">743</span><br><span class="line">744</span><br><span class="line">745</span><br><span class="line">746</span><br><span class="line">747</span><br><span class="line">748</span><br><span class="line">749</span><br><span class="line">750</span><br><span class="line">751</span><br><span class="line">752</span><br><span class="line">753</span><br><span class="line">754</span><br><span class="line">755</span><br><span class="line">756</span><br><span class="line">757</span><br><span class="line">758</span><br><span class="line">759</span><br><span class="line">760</span><br><span class="line">761</span><br><span class="line">762</span><br><span class="line">763</span><br><span class="line">764</span><br><span class="line">765</span><br><span class="line">766</span><br><span class="line">767</span><br><span class="line">768</span><br><span class="line">769</span><br><span class="line">770</span><br><span class="line">771</span><br><span class="line">772</span><br><span class="line">773</span><br><span class="line">774</span><br><span class="line">775</span><br><span class="line">776</span><br><span class="line">777</span><br><span class="line">778</span><br><span class="line">779</span><br><span class="line">780</span><br><span class="line">781</span><br><span class="line">782</span><br><span class="line">783</span><br><span class="line">784</span><br><span class="line">785</span><br><span class="line">786</span><br><span class="line">787</span><br><span class="line">788</span><br><span class="line">789</span><br><span class="line">790</span><br><span class="line">791</span><br><span class="line">792</span><br><span class="line">793</span><br><span class="line">794</span><br><span class="line">795</span><br><span class="line">796</span><br><span class="line">797</span><br><span class="line">798</span><br><span class="line">799</span><br><span class="line">800</span><br><span class="line">801</span><br><span class="line">802</span><br><span class="line">803</span><br><span class="line">804</span><br><span class="line">805</span><br><span class="line">806</span><br><span class="line">807</span><br><span class="line">808</span><br><span class="line">809</span><br><span class="line">810</span><br><span class="line">811</span><br><span class="line">812</span><br><span class="line">813</span><br><span class="line">814</span><br><span class="line">815</span><br><span class="line">816</span><br><span class="line">817</span><br><span class="line">818</span><br><span class="line">819</span><br><span class="line">820</span><br><span class="line">821</span><br><span class="line">822</span><br><span class="line">823</span><br><span class="line">824</span><br><span class="line">825</span><br><span class="line">826</span><br><span class="line">827</span><br><span class="line">828</span><br><span class="line">829</span><br><span class="line">830</span><br><span class="line">831</span><br><span class="line">832</span><br><span class="line">833</span><br><span class="line">834</span><br><span class="line">835</span><br><span class="line">836</span><br><span class="line">837</span><br><span class="line">838</span><br><span class="line">839</span><br><span class="line">840</span><br><span class="line">841</span><br><span class="line">842</span><br><span class="line">843</span><br><span class="line">844</span><br><span class="line">845</span><br><span class="line">846</span><br><span class="line">847</span><br><span class="line">848</span><br><span class="line">849</span><br><span class="line">850</span><br><span class="line">851</span><br><span class="line">852</span><br><span class="line">853</span><br><span class="line">854</span><br><span class="line">855</span><br><span class="line">856</span><br><span class="line">857</span><br><span class="line">858</span><br><span class="line">859</span><br><span class="line">860</span><br><span class="line">861</span><br><span class="line">862</span><br><span class="line">863</span><br><span class="line">864</span><br><span class="line">865</span><br><span class="line">866</span><br><span class="line">867</span><br><span class="line">868</span><br><span class="line">869</span><br><span class="line">870</span><br><span class="line">871</span><br><span class="line">872</span><br><span class="line">873</span><br><span class="line">874</span><br><span class="line">875</span><br><span class="line">876</span><br><span class="line">877</span><br><span class="line">878</span><br><span class="line">879</span><br><span class="line">880</span><br><span class="line">881</span><br><span class="line">882</span><br><span class="line">883</span><br><span class="line">884</span><br><span class="line">885</span><br><span class="line">886</span><br><span class="line">887</span><br><span class="line">888</span><br><span class="line">889</span><br><span class="line">890</span><br><span class="line">891</span><br><span class="line">892</span><br><span class="line">893</span><br><span class="line">894</span><br><span class="line">895</span><br><span class="line">896</span><br><span class="line">897</span><br><span class="line">898</span><br><span class="line">899</span><br><span class="line">900</span><br><span class="line">901</span><br><span class="line">902</span><br><span class="line">903</span><br><span class="line">904</span><br><span class="line">905</span><br><span class="line">906</span><br><span class="line">907</span><br><span class="line">908</span><br><span class="line">909</span><br><span class="line">910</span><br><span class="line">911</span><br><span class="line">912</span><br><span class="line">913</span><br><span class="line">914</span><br><span class="line">915</span><br><span class="line">916</span><br><span class="line">917</span><br><span class="line">918</span><br><span class="line">919</span><br><span class="line">920</span><br><span class="line">921</span><br><span class="line">922</span><br><span class="line">923</span><br><span class="line">924</span><br><span class="line">925</span><br><span class="line">926</span><br><span class="line">927</span><br><span class="line">928</span><br><span class="line">929</span><br><span class="line">930</span><br><span class="line">931</span><br><span class="line">932</span><br><span class="line">933</span><br><span class="line">934</span><br><span class="line">935</span><br><span class="line">936</span><br><span class="line">937</span><br><span class="line">938</span><br><span class="line">939</span><br><span class="line">940</span><br><span class="line">941</span><br><span class="line">942</span><br><span class="line">943</span><br><span class="line">944</span><br><span class="line">945</span><br><span class="line">946</span><br><span class="line">947</span><br><span class="line">948</span><br><span class="line">949</span><br><span class="line">950</span><br><span class="line">951</span><br><span class="line">952</span><br><span class="line">953</span><br><span class="line">954</span><br><span class="line">955</span><br><span class="line">956</span><br><span class="line">957</span><br><span class="line">958</span><br><span class="line">959</span><br><span class="line">960</span><br><span class="line">961</span><br><span class="line">962</span><br><span class="line">963</span><br><span class="line">964</span><br><span class="line">965</span><br><span class="line">966</span><br><span class="line">967</span><br><span class="line">968</span><br><span class="line">969</span><br><span class="line">970</span><br><span class="line">971</span><br><span class="line">972</span><br><span class="line">973</span><br><span class="line">974</span><br><span class="line">975</span><br><span class="line">976</span><br><span class="line">977</span><br><span class="line">978</span><br><span class="line">979</span><br><span class="line">980</span><br><span class="line">981</span><br><span class="line">982</span><br><span class="line">983</span><br><span class="line">984</span><br><span class="line">985</span><br><span class="line">986</span><br><span class="line">987</span><br><span class="line">988</span><br><span class="line">989</span><br><span class="line">990</span><br><span class="line">991</span><br><span class="line">992</span><br><span class="line">993</span><br><span class="line">994</span><br><span class="line">995</span><br><span class="line">996</span><br><span class="line">997</span><br><span class="line">998</span><br><span class="line">999</span><br><span class="line">1000</span><br><span class="line">1001</span><br><span class="line">1002</span><br><span class="line">1003</span><br><span class="line">1004</span><br><span class="line">1005</span><br><span class="line">1006</span><br><span class="line">1007</span><br><span class="line">1008</span><br><span class="line">1009</span><br><span class="line">1010</span><br><span class="line">1011</span><br><span class="line">1012</span><br><span class="line">1013</span><br><span class="line">1014</span><br><span class="line">1015</span><br><span class="line">1016</span><br><span class="line">1017</span><br><span class="line">1018</span><br><span class="line">1019</span><br><span class="line">1020</span><br><span class="line">1021</span><br><span class="line">1022</span><br><span class="line">1023</span><br><span class="line">1024</span><br><span class="line">1025</span><br><span class="line">1026</span><br><span class="line">1027</span><br><span class="line">1028</span><br><span class="line">1029</span><br><span class="line">1030</span><br><span class="line">1031</span><br><span class="line">1032</span><br><span class="line">1033</span><br><span class="line">1034</span><br><span class="line">1035</span><br><span class="line">1036</span><br><span class="line">1037</span><br><span class="line">1038</span><br><span class="line">1039</span><br><span class="line">1040</span><br><span class="line">1041</span><br><span class="line">1042</span><br><span class="line">1043</span><br><span class="line">1044</span><br><span class="line">1045</span><br><span class="line">1046</span><br><span class="line">1047</span><br><span class="line">1048</span><br><span class="line">1049</span><br><span class="line">1050</span><br><span class="line">1051</span><br><span class="line">1052</span><br><span class="line">1053</span><br><span class="line">1054</span><br><span class="line">1055</span><br><span class="line">1056</span><br><span class="line">1057</span><br><span class="line">1058</span><br><span class="line">1059</span><br><span class="line">1060</span><br><span class="line">1061</span><br><span class="line">1062</span><br><span class="line">1063</span><br><span class="line">1064</span><br><span class="line">1065</span><br><span class="line">1066</span><br><span class="line">1067</span><br><span class="line">1068</span><br><span class="line">1069</span><br><span class="line">1070</span><br><span class="line">1071</span><br><span class="line">1072</span><br><span class="line">1073</span><br><span class="line">1074</span><br><span class="line">1075</span><br><span class="line">1076</span><br><span class="line">1077</span><br><span class="line">1078</span><br><span class="line">1079</span><br><span class="line">1080</span><br><span class="line">1081</span><br><span class="line">1082</span><br><span class="line">1083</span><br><span class="line">1084</span><br><span class="line">1085</span><br><span class="line">1086</span><br><span class="line">1087</span><br><span class="line">1088</span><br><span class="line">1089</span><br><span class="line">1090</span><br><span class="line">1091</span><br><span class="line">1092</span><br><span class="line">1093</span><br><span class="line">1094</span><br><span class="line">1095</span><br><span class="line">1096</span><br><span class="line">1097</span><br><span class="line">1098</span><br><span class="line">1099</span><br><span class="line">1100</span><br><span class="line">1101</span><br><span class="line">1102</span><br><span class="line">1103</span><br><span class="line">1104</span><br><span class="line">1105</span><br><span class="line">1106</span><br><span class="line">1107</span><br><span class="line">1108</span><br><span class="line">1109</span><br><span class="line">1110</span><br><span class="line">1111</span><br><span class="line">1112</span><br><span class="line">1113</span><br><span class="line">1114</span><br><span class="line">1115</span><br><span class="line">1116</span><br><span class="line">1117</span><br><span class="line">1118</span><br><span class="line">1119</span><br><span class="line">1120</span><br><span class="line">1121</span><br><span class="line">1122</span><br><span class="line">1123</span><br><span class="line">1124</span><br><span class="line">1125</span><br><span class="line">1126</span><br><span class="line">1127</span><br><span class="line">1128</span><br><span class="line">1129</span><br><span class="line">1130</span><br><span class="line">1131</span><br><span class="line">1132</span><br><span class="line">1133</span><br><span class="line">1134</span><br><span class="line">1135</span><br><span class="line">1136</span><br><span class="line">1137</span><br><span class="line">1138</span><br><span class="line">1139</span><br><span class="line">1140</span><br><span class="line">1141</span><br><span class="line">1142</span><br><span class="line">1143</span><br><span class="line">1144</span><br><span class="line">1145</span><br><span class="line">1146</span><br><span class="line">1147</span><br><span class="line">1148</span><br><span class="line">1149</span><br><span class="line">1150</span><br><span class="line">1151</span><br><span class="line">1152</span><br><span class="line">1153</span><br><span class="line">1154</span><br><span class="line">1155</span><br><span class="line">1156</span><br><span class="line">1157</span><br><span class="line">1158</span><br><span class="line">1159</span><br><span class="line">1160</span><br><span class="line">1161</span><br><span class="line">1162</span><br><span class="line">1163</span><br><span class="line">1164</span><br><span class="line">1165</span><br><span class="line">1166</span><br><span class="line">1167</span><br><span class="line">1168</span><br><span class="line">1169</span><br><span class="line">1170</span><br><span class="line">1171</span><br><span class="line">1172</span><br><span class="line">1173</span><br><span class="line">1174</span><br><span class="line">1175</span><br><span class="line">1176</span><br><span class="line">1177</span><br><span class="line">1178</span><br><span class="line">1179</span><br><span class="line">1180</span><br><span class="line">1181</span><br><span class="line">1182</span><br><span class="line">1183</span><br><span class="line">1184</span><br><span class="line">1185</span><br><span class="line">1186</span><br><span class="line">1187</span><br><span class="line">1188</span><br><span class="line">1189</span><br><span class="line">1190</span><br><span class="line">1191</span><br><span class="line">1192</span><br><span class="line">1193</span><br><span class="line">1194</span><br><span class="line">1195</span><br><span class="line">1196</span><br><span class="line">1197</span><br><span class="line">1198</span><br><span class="line">1199</span><br><span class="line">1200</span><br><span class="line">1201</span><br><span class="line">1202</span><br><span class="line">1203</span><br><span class="line">1204</span><br><span class="line">1205</span><br><span class="line">1206</span><br><span class="line">1207</span><br><span class="line">1208</span><br><span class="line">1209</span><br><span class="line">1210</span><br><span class="line">1211</span><br><span class="line">1212</span><br><span class="line">1213</span><br><span class="line">1214</span><br><span class="line">1215</span><br><span class="line">1216</span><br><span class="line">1217</span><br><span class="line">1218</span><br><span class="line">1219</span><br><span class="line">1220</span><br><span class="line">1221</span><br><span class="line">1222</span><br><span class="line">1223</span><br><span class="line">1224</span><br><span class="line">1225</span><br><span class="line">1226</span><br><span class="line">1227</span><br><span class="line">1228</span><br><span class="line">1229</span><br><span class="line">1230</span><br><span class="line">1231</span><br><span class="line">1232</span><br><span class="line">1233</span><br><span class="line">1234</span><br><span class="line">1235</span><br><span class="line">1236</span><br><span class="line">1237</span><br><span class="line">1238</span><br><span class="line">1239</span><br><span class="line">1240</span><br><span class="line">1241</span><br><span class="line">1242</span><br><span class="line">1243</span><br><span class="line">1244</span><br><span class="line">1245</span><br><span class="line">1246</span><br><span class="line">1247</span><br><span class="line">1248</span><br><span class="line">1249</span><br><span class="line">1250</span><br><span class="line">1251</span><br><span class="line">1252</span><br><span class="line">1253</span><br><span class="line">1254</span><br><span class="line">1255</span><br><span class="line">1256</span><br><span class="line">1257</span><br><span class="line">1258</span><br><span class="line">1259</span><br><span class="line">1260</span><br><span class="line">1261</span><br><span class="line">1262</span><br><span class="line">1263</span><br><span class="line">1264</span><br><span class="line">1265</span><br><span class="line">1266</span><br><span class="line">1267</span><br><span class="line">1268</span><br><span class="line">1269</span><br><span class="line">1270</span><br><span class="line">1271</span><br><span class="line">1272</span><br><span class="line">1273</span><br><span class="line">1274</span><br><span class="line">1275</span><br><span class="line">1276</span><br><span class="line">1277</span><br><span class="line">1278</span><br><span class="line">1279</span><br><span class="line">1280</span><br><span class="line">1281</span><br><span class="line">1282</span><br><span class="line">1283</span><br><span class="line">1284</span><br><span class="line">1285</span><br><span class="line">1286</span><br><span class="line">1287</span><br><span class="line">1288</span><br><span class="line">1289</span><br><span class="line">1290</span><br><span class="line">1291</span><br><span class="line">1292</span><br><span class="line">1293</span><br><span class="line">1294</span><br><span class="line">1295</span><br><span class="line">1296</span><br><span class="line">1297</span><br><span class="line">1298</span><br><span class="line">1299</span><br><span class="line">1300</span><br><span class="line">1301</span><br><span class="line">1302</span><br><span class="line">1303</span><br><span class="line">1304</span><br><span class="line">1305</span><br><span class="line">1306</span><br><span class="line">1307</span><br><span class="line">1308</span><br><span class="line">1309</span><br><span class="line">1310</span><br><span class="line">1311</span><br><span class="line">1312</span><br><span class="line">1313</span><br><span class="line">1314</span><br><span class="line">1315</span><br><span class="line">1316</span><br><span class="line">1317</span><br><span class="line">1318</span><br><span class="line">1319</span><br><span class="line">1320</span><br><span class="line">1321</span><br><span class="line">1322</span><br><span class="line">1323</span><br><span class="line">1324</span><br><span class="line">1325</span><br><span class="line">1326</span><br><span class="line">1327</span><br><span class="line">1328</span><br><span class="line">1329</span><br><span class="line">1330</span><br><span class="line">1331</span><br><span class="line">1332</span><br><span class="line">1333</span><br><span class="line">1334</span><br><span class="line">1335</span><br><span class="line">1336</span><br><span class="line">1337</span><br><span class="line">1338</span><br><span class="line">1339</span><br><span class="line">1340</span><br><span class="line">1341</span><br><span class="line">1342</span><br><span class="line">1343</span><br><span class="line">1344</span><br><span class="line">1345</span><br><span class="line">1346</span><br><span class="line">1347</span><br><span class="line">1348</span><br><span class="line">1349</span><br><span class="line">1350</span><br><span class="line">1351</span><br><span class="line">1352</span><br><span class="line">1353</span><br><span class="line">1354</span><br><span class="line">1355</span><br><span class="line">1356</span><br><span class="line">1357</span><br><span class="line">1358</span><br><span class="line">1359</span><br><span class="line">1360</span><br><span class="line">1361</span><br><span class="line">1362</span><br><span class="line">1363</span><br><span class="line">1364</span><br><span class="line">1365</span><br><span class="line">1366</span><br><span class="line">1367</span><br><span class="line">1368</span><br><span class="line">1369</span><br><span class="line">1370</span><br><span class="line">1371</span><br><span class="line">1372</span><br><span class="line">1373</span><br><span class="line">1374</span><br><span class="line">1375</span><br><span class="line">1376</span><br><span class="line">1377</span><br><span class="line">1378</span><br><span class="line">1379</span><br><span class="line">1380</span><br><span class="line">1381</span><br><span class="line">1382</span><br><span class="line">1383</span><br><span class="line">1384</span><br><span class="line">1385</span><br><span class="line">1386</span><br><span class="line">1387</span><br><span class="line">1388</span><br><span class="line">1389</span><br><span class="line">1390</span><br><span class="line">1391</span><br><span class="line">1392</span><br><span class="line">1393</span><br><span class="line">1394</span><br><span class="line">1395</span><br><span class="line">1396</span><br><span class="line">1397</span><br><span class="line">1398</span><br><span class="line">1399</span><br><span class="line">1400</span><br><span class="line">1401</span><br><span class="line">1402</span><br><span class="line">1403</span><br><span class="line">1404</span><br><span class="line">1405</span><br><span class="line">1406</span><br><span class="line">1407</span><br><span class="line">1408</span><br><span class="line">1409</span><br><span class="line">1410</span><br><span class="line">1411</span><br><span class="line">1412</span><br><span class="line">1413</span><br><span class="line">1414</span><br><span class="line">1415</span><br><span class="line">1416</span><br><span class="line">1417</span><br><span class="line">1418</span><br><span class="line">1419</span><br><span class="line">1420</span><br><span class="line">1421</span><br><span class="line">1422</span><br><span class="line">1423</span><br><span class="line">1424</span><br><span class="line">1425</span><br><span class="line">1426</span><br><span class="line">1427</span><br><span class="line">1428</span><br><span class="line">1429</span><br><span class="line">1430</span><br><span class="line">1431</span><br><span class="line">1432</span><br><span class="line">1433</span><br><span class="line">1434</span><br><span class="line">1435</span><br><span class="line">1436</span><br><span class="line">1437</span><br><span class="line">1438</span><br><span class="line">1439</span><br><span class="line">1440</span><br><span class="line">1441</span><br><span class="line">1442</span><br><span class="line">1443</span><br><span class="line">1444</span><br><span class="line">1445</span><br><span class="line">1446</span><br><span class="line">1447</span><br><span class="line">1448</span><br><span class="line">1449</span><br><span class="line">1450</span><br><span class="line">1451</span><br><span class="line">1452</span><br><span class="line">1453</span><br><span class="line">1454</span><br><span class="line">1455</span><br><span class="line">1456</span><br><span class="line">1457</span><br><span class="line">1458</span><br><span class="line">1459</span><br><span class="line">1460</span><br><span class="line">1461</span><br><span class="line">1462</span><br><span class="line">1463</span><br><span class="line">1464</span><br><span class="line">1465</span><br><span class="line">1466</span><br><span class="line">1467</span><br><span class="line">1468</span><br><span class="line">1469</span><br><span class="line">1470</span><br><span class="line">1471</span><br><span class="line">1472</span><br><span class="line">1473</span><br><span class="line">1474</span><br><span class="line">1475</span><br><span class="line">1476</span><br><span class="line">1477</span><br><span class="line">1478</span><br><span class="line">1479</span><br><span class="line">1480</span><br><span class="line">1481</span><br><span class="line">1482</span><br><span class="line">1483</span><br><span class="line">1484</span><br><span class="line">1485</span><br><span class="line">1486</span><br><span class="line">1487</span><br><span class="line">1488</span><br><span class="line">1489</span><br><span class="line">1490</span><br><span class="line">1491</span><br><span class="line">1492</span><br><span class="line">1493</span><br><span class="line">1494</span><br><span class="line">1495</span><br><span class="line">1496</span><br><span class="line">1497</span><br><span class="line">1498</span><br><span class="line">1499</span><br><span class="line">1500</span><br><span class="line">1501</span><br><span class="line">1502</span><br><span class="line">1503</span><br><span class="line">1504</span><br><span class="line">1505</span><br><span class="line">1506</span><br><span class="line">1507</span><br><span class="line">1508</span><br><span class="line">1509</span><br><span class="line">1510</span><br><span class="line">1511</span><br><span class="line">1512</span><br><span class="line">1513</span><br><span class="line">1514</span><br><span class="line">1515</span><br><span class="line">1516</span><br><span class="line">1517</span><br><span class="line">1518</span><br><span class="line">1519</span><br><span class="line">1520</span><br><span class="line">1521</span><br><span class="line">1522</span><br><span class="line">1523</span><br><span class="line">1524</span><br><span class="line">1525</span><br><span class="line">1526</span><br><span class="line">1527</span><br><span class="line">1528</span><br><span class="line">1529</span><br><span class="line">1530</span><br><span class="line">1531</span><br><span class="line">1532</span><br><span class="line">1533</span><br><span class="line">1534</span><br><span class="line">1535</span><br><span class="line">1536</span><br><span class="line">1537</span><br><span class="line">1538</span><br><span class="line">1539</span><br><span class="line">1540</span><br><span class="line">1541</span><br><span class="line">1542</span><br><span class="line">1543</span><br><span class="line">1544</span><br><span class="line">1545</span><br><span class="line">1546</span><br><span class="line">1547</span><br><span class="line">1548</span><br><span class="line">1549</span><br><span class="line">1550</span><br><span class="line">1551</span><br><span class="line">1552</span><br><span class="line">1553</span><br><span class="line">1554</span><br><span class="line">1555</span><br><span class="line">1556</span><br><span class="line">1557</span><br><span class="line">1558</span><br><span class="line">1559</span><br><span class="line">1560</span><br><span class="line">1561</span><br><span class="line">1562</span><br><span class="line">1563</span><br><span class="line">1564</span><br><span class="line">1565</span><br><span class="line">1566</span><br><span class="line">1567</span><br><span class="line">1568</span><br><span class="line">1569</span><br><span class="line">1570</span><br><span class="line">1571</span><br><span class="line">1572</span><br><span class="line">1573</span><br><span class="line">1574</span><br><span class="line">1575</span><br><span class="line">1576</span><br><span class="line">1577</span><br><span class="line">1578</span><br><span class="line">1579</span><br><span class="line">1580</span><br><span class="line">1581</span><br><span class="line">1582</span><br><span class="line">1583</span><br><span class="line">1584</span><br><span class="line">1585</span><br><span class="line">1586</span><br><span class="line">1587</span><br><span class="line">1588</span><br><span class="line">1589</span><br><span class="line">1590</span><br><span class="line">1591</span><br><span class="line">1592</span><br><span class="line">1593</span><br><span class="line">1594</span><br><span class="line">1595</span><br><span class="line">1596</span><br><span class="line">1597</span><br><span class="line">1598</span><br><span class="line">1599</span><br><span class="line">1600</span><br><span class="line">1601</span><br><span class="line">1602</span><br><span class="line">1603</span><br><span class="line">1604</span><br><span class="line">1605</span><br><span class="line">1606</span><br><span class="line">1607</span><br><span class="line">1608</span><br><span class="line">1609</span><br><span class="line">1610</span><br><span class="line">1611</span><br><span class="line">1612</span><br><span class="line">1613</span><br><span class="line">1614</span><br><span class="line">1615</span><br><span class="line">1616</span><br><span class="line">1617</span><br><span class="line">1618</span><br><span class="line">1619</span><br><span class="line">1620</span><br><span class="line">1621</span><br><span class="line">1622</span><br><span class="line">1623</span><br><span class="line">1624</span><br><span class="line">1625</span><br><span class="line">1626</span><br><span class="line">1627</span><br><span class="line">1628</span><br><span class="line">1629</span><br><span class="line">1630</span><br><span class="line">1631</span><br><span class="line">1632</span><br><span class="line">1633</span><br><span class="line">1634</span><br><span class="line">1635</span><br><span class="line">1636</span><br><span class="line">1637</span><br><span class="line">1638</span><br><span class="line">1639</span><br><span class="line">1640</span><br><span class="line">1641</span><br><span class="line">1642</span><br><span class="line">1643</span><br><span class="line">1644</span><br><span class="line">1645</span><br><span class="line">1646</span><br><span class="line">1647</span><br><span class="line">1648</span><br><span class="line">1649</span><br><span class="line">1650</span><br><span class="line">1651</span><br><span class="line">1652</span><br><span class="line">1653</span><br><span class="line">1654</span><br><span class="line">1655</span><br><span class="line">1656</span><br><span class="line">1657</span><br><span class="line">1658</span><br><span class="line">1659</span><br><span class="line">1660</span><br><span class="line">1661</span><br><span class="line">1662</span><br><span class="line">1663</span><br><span class="line">1664</span><br><span class="line">1665</span><br><span class="line">1666</span><br><span class="line">1667</span><br><span class="line">1668</span><br><span class="line">1669</span><br><span class="line">1670</span><br><span class="line">1671</span><br><span class="line">1672</span><br><span class="line">1673</span><br><span class="line">1674</span><br><span class="line">1675</span><br><span class="line">1676</span><br><span class="line">1677</span><br><span class="line">1678</span><br><span class="line">1679</span><br><span class="line">1680</span><br><span class="line">1681</span><br><span class="line">1682</span><br><span class="line">1683</span><br><span class="line">1684</span><br><span class="line">1685</span><br><span class="line">1686</span><br><span class="line">1687</span><br><span class="line">1688</span><br><span class="line">1689</span><br><span class="line">1690</span><br><span class="line">1691</span><br><span class="line">1692</span><br><span class="line">1693</span><br><span class="line">1694</span><br><span class="line">1695</span><br><span class="line">1696</span><br><span class="line">1697</span><br><span class="line">1698</span><br><span class="line">1699</span><br><span class="line">1700</span><br><span class="line">1701</span><br><span class="line">1702</span><br><span class="line">1703</span><br><span class="line">1704</span><br><span class="line">1705</span><br><span class="line">1706</span><br><span class="line">1707</span><br><span class="line">1708</span><br><span class="line">1709</span><br><span class="line">1710</span><br><span class="line">1711</span><br><span class="line">1712</span><br><span class="line">1713</span><br><span class="line">1714</span><br><span class="line">1715</span><br><span class="line">1716</span><br><span class="line">1717</span><br><span class="line">1718</span><br><span class="line">1719</span><br><span class="line">1720</span><br><span class="line">1721</span><br><span class="line">1722</span><br><span class="line">1723</span><br><span class="line">1724</span><br><span class="line">1725</span><br><span class="line">1726</span><br><span class="line">1727</span><br><span class="line">1728</span><br><span class="line">1729</span><br><span class="line">1730</span><br><span class="line">1731</span><br><span class="line">1732</span><br><span class="line">1733</span><br><span class="line">1734</span><br><span class="line">1735</span><br><span class="line">1736</span><br><span class="line">1737</span><br><span class="line">1738</span><br><span class="line">1739</span><br><span class="line">1740</span><br><span class="line">1741</span><br><span class="line">1742</span><br><span class="line">1743</span><br><span class="line">1744</span><br><span class="line">1745</span><br><span class="line">1746</span><br><span class="line">1747</span><br><span class="line">1748</span><br><span class="line">1749</span><br><span class="line">1750</span><br><span class="line">1751</span><br><span class="line">1752</span><br><span class="line">1753</span><br><span class="line">1754</span><br><span class="line">1755</span><br><span class="line">1756</span><br><span class="line">1757</span><br><span class="line">1758</span><br><span class="line">1759</span><br><span class="line">1760</span><br><span class="line">1761</span><br><span class="line">1762</span><br><span class="line">1763</span><br><span class="line">1764</span><br><span class="line">1765</span><br><span class="line">1766</span><br><span class="line">1767</span><br><span class="line">1768</span><br><span class="line">1769</span><br><span class="line">1770</span><br><span class="line">1771</span><br><span class="line">1772</span><br><span class="line">1773</span><br><span class="line">1774</span><br><span class="line">1775</span><br><span class="line">1776</span><br><span class="line">1777</span><br><span class="line">1778</span><br><span class="line">1779</span><br><span class="line">1780</span><br><span class="line">1781</span><br><span class="line">1782</span><br><span class="line">1783</span><br><span class="line">1784</span><br><span class="line">1785</span><br><span class="line">1786</span><br><span class="line">1787</span><br><span class="line">1788</span><br><span class="line">1789</span><br><span class="line">1790</span><br><span class="line">1791</span><br><span class="line">1792</span><br><span class="line">1793</span><br><span class="line">1794</span><br><span class="line">1795</span><br><span class="line">1796</span><br><span class="line">1797</span><br><span class="line">1798</span><br><span class="line">1799</span><br><span class="line">1800</span><br><span class="line">1801</span><br><span class="line">1802</span><br><span class="line">1803</span><br><span class="line">1804</span><br><span class="line">1805</span><br><span class="line">1806</span><br><span class="line">1807</span><br><span class="line">1808</span><br><span class="line">1809</span><br><span class="line">1810</span><br><span class="line">1811</span><br><span class="line">1812</span><br><span class="line">1813</span><br><span class="line">1814</span><br><span class="line">1815</span><br><span class="line">1816</span><br><span class="line">1817</span><br><span class="line">1818</span><br><span class="line">1819</span><br><span class="line">1820</span><br><span class="line">1821</span><br><span class="line">1822</span><br><span class="line">1823</span><br><span class="line">1824</span><br><span class="line">1825</span><br><span class="line">1826</span><br><span class="line">1827</span><br><span class="line">1828</span><br><span class="line">1829</span><br><span class="line">1830</span><br><span class="line">1831</span><br><span class="line">1832</span><br><span class="line">1833</span><br><span class="line">1834</span><br><span class="line">1835</span><br><span class="line">1836</span><br><span class="line">1837</span><br><span class="line">1838</span><br><span class="line">1839</span><br><span class="line">1840</span><br><span class="line">1841</span><br><span class="line">1842</span><br><span class="line">1843</span><br><span class="line">1844</span><br><span class="line">1845</span><br><span class="line">1846</span><br><span class="line">1847</span><br><span class="line">1848</span><br><span class="line">1849</span><br><span class="line">1850</span><br><span class="line">1851</span><br><span class="line">1852</span><br><span class="line">1853</span><br><span class="line">1854</span><br><span class="line">1855</span><br><span class="line">1856</span><br><span class="line">1857</span><br><span class="line">1858</span><br><span class="line">1859</span><br><span class="line">1860</span><br><span class="line">1861</span><br><span class="line">1862</span><br><span class="line">1863</span><br><span class="line">1864</span><br><span class="line">1865</span><br><span class="line">1866</span><br><span class="line">1867</span><br><span class="line">1868</span><br><span class="line">1869</span><br><span class="line">1870</span><br><span class="line">1871</span><br><span class="line">1872</span><br><span class="line">1873</span><br><span class="line">1874</span><br><span class="line">1875</span><br><span class="line">1876</span><br><span class="line">1877</span><br><span class="line">1878</span><br><span class="line">1879</span><br><span class="line">1880</span><br><span class="line">1881</span><br><span class="line">1882</span><br><span class="line">1883</span><br><span class="line">1884</span><br><span class="line">1885</span><br><span class="line">1886</span><br><span class="line">1887</span><br><span class="line">1888</span><br><span class="line">1889</span><br><span class="line">1890</span><br><span class="line">1891</span><br><span class="line">1892</span><br><span class="line">1893</span><br><span class="line">1894</span><br><span class="line">1895</span><br><span class="line">1896</span><br><span class="line">1897</span><br><span class="line">1898</span><br><span class="line">1899</span><br><span class="line">1900</span><br><span class="line">1901</span><br><span class="line">1902</span><br><span class="line">1903</span><br><span class="line">1904</span><br><span class="line">1905</span><br><span class="line">1906</span><br><span class="line">1907</span><br><span class="line">1908</span><br><span class="line">1909</span><br><span class="line">1910</span><br><span class="line">1911</span><br><span class="line">1912</span><br><span class="line">1913</span><br><span class="line">1914</span><br><span class="line">1915</span><br><span class="line">1916</span><br><span class="line">1917</span><br><span class="line">1918</span><br><span class="line">1919</span><br><span class="line">1920</span><br><span class="line">1921</span><br><span class="line">1922</span><br><span class="line">1923</span><br><span class="line">1924</span><br><span class="line">1925</span><br><span class="line">1926</span><br><span class="line">1927</span><br><span class="line">1928</span><br><span class="line">1929</span><br><span class="line">1930</span><br><span class="line">1931</span><br><span class="line">1932</span><br><span class="line">1933</span><br><span class="line">1934</span><br><span class="line">1935</span><br><span class="line">1936</span><br><span class="line">1937</span><br><span class="line">1938</span><br><span class="line">1939</span><br><span class="line">1940</span><br><span class="line">1941</span><br><span class="line">1942</span><br><span class="line">1943</span><br><span class="line">1944</span><br><span class="line">1945</span><br><span class="line">1946</span><br><span class="line">1947</span><br><span class="line">1948</span><br><span class="line">1949</span><br><span class="line">1950</span><br><span class="line">1951</span><br><span class="line">1952</span><br><span class="line">1953</span><br><span class="line">1954</span><br><span class="line">1955</span><br><span class="line">1956</span><br><span class="line">1957</span><br><span class="line">1958</span><br><span class="line">1959</span><br><span class="line">1960</span><br><span class="line">1961</span><br><span class="line">1962</span><br><span class="line">1963</span><br><span class="line">1964</span><br><span class="line">1965</span><br><span class="line">1966</span><br><span class="line">1967</span><br><span class="line">1968</span><br><span class="line">1969</span><br><span class="line">1970</span><br><span class="line">1971</span><br><span class="line">1972</span><br><span class="line">1973</span><br><span class="line">1974</span><br><span class="line">1975</span><br><span class="line">1976</span><br><span class="line">1977</span><br><span class="line">1978</span><br><span class="line">1979</span><br><span class="line">1980</span><br><span class="line">1981</span><br><span class="line">1982</span><br><span class="line">1983</span><br><span class="line">1984</span><br><span class="line">1985</span><br><span class="line">1986</span><br><span class="line">1987</span><br><span class="line">1988</span><br><span class="line">1989</span><br><span class="line">1990</span><br><span class="line">1991</span><br><span class="line">1992</span><br><span class="line">1993</span><br><span class="line">1994</span><br><span class="line">1995</span><br><span class="line">1996</span><br><span class="line">1997</span><br><span class="line">1998</span><br><span class="line">1999</span><br><span class="line">2000</span><br><span class="line">2001</span><br><span class="line">2002</span><br><span class="line">2003</span><br><span class="line">2004</span><br><span class="line">2005</span><br><span class="line">2006</span><br><span class="line">2007</span><br><span class="line">2008</span><br><span class="line">2009</span><br><span class="line">2010</span><br><span class="line">2011</span><br><span class="line">2012</span><br><span class="line">2013</span><br><span class="line">2014</span><br><span class="line">2015</span><br><span class="line">2016</span><br><span class="line">2017</span><br><span class="line">2018</span><br><span class="line">2019</span><br><span class="line">2020</span><br><span class="line">2021</span><br><span class="line">2022</span><br><span class="line">2023</span><br><span class="line">2024</span><br><span class="line">2025</span><br><span class="line">2026</span><br><span class="line">2027</span><br><span class="line">2028</span><br><span class="line">2029</span><br><span class="line">2030</span><br><span class="line">2031</span><br><span class="line">2032</span><br><span class="line">2033</span><br><span class="line">2034</span><br><span class="line">2035</span><br><span class="line">2036</span><br><span class="line">2037</span><br><span class="line">2038</span><br><span class="line">2039</span><br><span class="line">2040</span><br><span class="line">2041</span><br><span class="line">2042</span><br><span class="line">2043</span><br><span class="line">2044</span><br><span class="line">2045</span><br><span class="line">2046</span><br><span class="line">2047</span><br><span class="line">2048</span><br><span class="line">2049</span><br><span class="line">2050</span><br><span class="line">2051</span><br><span class="line">2052</span><br><span class="line">2053</span><br><span class="line">2054</span><br><span class="line">2055</span><br><span class="line">2056</span><br><span class="line">2057</span><br><span class="line">2058</span><br><span class="line">2059</span><br><span class="line">2060</span><br><span class="line">2061</span><br><span class="line">2062</span><br><span class="line">2063</span><br><span class="line">2064</span><br><span class="line">2065</span><br><span class="line">2066</span><br><span class="line">2067</span><br><span class="line">2068</span><br><span class="line">2069</span><br><span class="line">2070</span><br><span class="line">2071</span><br><span class="line">2072</span><br><span class="line">2073</span><br><span class="line">2074</span><br><span class="line">2075</span><br><span class="line">2076</span><br><span class="line">2077</span><br><span class="line">2078</span><br><span class="line">2079</span><br><span class="line">2080</span><br><span class="line">2081</span><br><span class="line">2082</span><br><span class="line">2083</span><br><span class="line">2084</span><br><span class="line">2085</span><br><span class="line">2086</span><br><span class="line">2087</span><br><span class="line">2088</span><br><span class="line">2089</span><br><span class="line">2090</span><br><span class="line">2091</span><br><span class="line">2092</span><br><span class="line">2093</span><br><span class="line">2094</span><br><span class="line">2095</span><br><span class="line">2096</span><br><span class="line">2097</span><br><span class="line">2098</span><br><span class="line">2099</span><br><span class="line">2100</span><br><span class="line">2101</span><br><span class="line">2102</span><br><span class="line">2103</span><br><span class="line">2104</span><br><span class="line">2105</span><br><span class="line">2106</span><br><span class="line">2107</span><br><span class="line">2108</span><br><span class="line">2109</span><br><span class="line">2110</span><br><span class="line">2111</span><br><span class="line">2112</span><br><span class="line">2113</span><br><span class="line">2114</span><br><span class="line">2115</span><br><span class="line">2116</span><br><span class="line">2117</span><br><span class="line">2118</span><br><span class="line">2119</span><br><span class="line">2120</span><br><span class="line">2121</span><br><span class="line">2122</span><br><span class="line">2123</span><br><span class="line">2124</span><br><span class="line">2125</span><br><span class="line">2126</span><br><span class="line">2127</span><br><span class="line">2128</span><br><span class="line">2129</span><br><span class="line">2130</span><br><span class="line">2131</span><br><span class="line">2132</span><br><span class="line">2133</span><br><span class="line">2134</span><br><span class="line">2135</span><br><span class="line">2136</span><br><span class="line">2137</span><br><span class="line">2138</span><br><span class="line">2139</span><br><span class="line">2140</span><br><span class="line">2141</span><br><span class="line">2142</span><br><span class="line">2143</span><br><span class="line">2144</span><br><span class="line">2145</span><br><span class="line">2146</span><br><span class="line">2147</span><br><span class="line">2148</span><br><span class="line">2149</span><br><span class="line">2150</span><br><span class="line">2151</span><br><span class="line">2152</span><br><span class="line">2153</span><br><span class="line">2154</span><br><span class="line">2155</span><br><span class="line">2156</span><br><span class="line">2157</span><br><span class="line">2158</span><br><span class="line">2159</span><br><span class="line">2160</span><br><span class="line">2161</span><br><span class="line">2162</span><br><span class="line">2163</span><br><span class="line">2164</span><br><span class="line">2165</span><br><span class="line">2166</span><br><span class="line">2167</span><br><span class="line">2168</span><br><span class="line">2169</span><br><span class="line">2170</span><br><span class="line">2171</span><br><span class="line">2172</span><br><span class="line">2173</span><br><span class="line">2174</span><br><span class="line">2175</span><br><span class="line">2176</span><br><span class="line">2177</span><br><span class="line">2178</span><br><span class="line">2179</span><br><span class="line">2180</span><br><span class="line">2181</span><br><span class="line">2182</span><br><span class="line">2183</span><br><span class="line">2184</span><br><span class="line">2185</span><br><span class="line">2186</span><br><span class="line">2187</span><br><span class="line">2188</span><br><span class="line">2189</span><br><span class="line">2190</span><br><span class="line">2191</span><br><span class="line">2192</span><br><span class="line">2193</span><br><span class="line">2194</span><br><span class="line">2195</span><br><span class="line">2196</span><br><span class="line">2197</span><br><span class="line">2198</span><br><span class="line">2199</span><br><span class="line">2200</span><br><span class="line">2201</span><br><span class="line">2202</span><br><span class="line">2203</span><br><span class="line">2204</span><br><span class="line">2205</span><br><span class="line">2206</span><br><span class="line">2207</span><br><span class="line">2208</span><br><span class="line">2209</span><br><span class="line">2210</span><br><span class="line">2211</span><br><span class="line">2212</span><br><span class="line">2213</span><br><span class="line">2214</span><br><span class="line">2215</span><br><span class="line">2216</span><br><span class="line">2217</span><br><span class="line">2218</span><br><span class="line">2219</span><br><span class="line">2220</span><br><span class="line">2221</span><br><span class="line">2222</span><br><span class="line">2223</span><br><span class="line">2224</span><br><span class="line">2225</span><br><span class="line">2226</span><br><span class="line">2227</span><br><span class="line">2228</span><br><span class="line">2229</span><br><span class="line">2230</span><br><span class="line">2231</span><br><span class="line">2232</span><br><span class="line">2233</span><br><span class="line">2234</span><br><span class="line">2235</span><br><span class="line">2236</span><br><span class="line">2237</span><br><span class="line">2238</span><br><span class="line">2239</span><br><span class="line">2240</span><br><span class="line">2241</span><br><span class="line">2242</span><br><span class="line">2243</span><br><span class="line">2244</span><br><span class="line">2245</span><br><span class="line">2246</span><br><span class="line">2247</span><br><span class="line">2248</span><br><span class="line">2249</span><br><span class="line">2250</span><br><span class="line">2251</span><br><span class="line">2252</span><br><span class="line">2253</span><br><span class="line">2254</span><br><span class="line">2255</span><br><span class="line">2256</span><br><span class="line">2257</span><br><span class="line">2258</span><br><span class="line">2259</span><br><span class="line">2260</span><br><span class="line">2261</span><br><span class="line">2262</span><br><span class="line">2263</span><br><span class="line">2264</span><br><span class="line">2265</span><br><span class="line">2266</span><br><span class="line">2267</span><br><span class="line">2268</span><br><span class="line">2269</span><br><span class="line">2270</span><br><span class="line">2271</span><br><span class="line">2272</span><br><span class="line">2273</span><br><span class="line">2274</span><br><span class="line">2275</span><br><span class="line">2276</span><br><span class="line">2277</span><br><span class="line">2278</span><br><span class="line">2279</span><br><span class="line">2280</span><br><span class="line">2281</span><br><span class="line">2282</span><br><span class="line">2283</span><br><span class="line">2284</span><br><span class="line">2285</span><br><span class="line">2286</span><br><span class="line">2287</span><br><span class="line">2288</span><br><span class="line">2289</span><br><span class="line">2290</span><br><span class="line">2291</span><br><span class="line">2292</span><br><span class="line">2293</span><br><span class="line">2294</span><br><span class="line">2295</span><br><span class="line">2296</span><br><span class="line">2297</span><br><span class="line">2298</span><br><span class="line">2299</span><br><span class="line">2300</span><br><span class="line">2301</span><br><span class="line">2302</span><br><span class="line">2303</span><br><span class="line">2304</span><br><span class="line">2305</span><br><span class="line">2306</span><br><span class="line">2307</span><br><span class="line">2308</span><br><span class="line">2309</span><br><span class="line">2310</span><br><span class="line">2311</span><br><span class="line">2312</span><br><span class="line">2313</span><br><span class="line">2314</span><br><span class="line">2315</span><br><span class="line">2316</span><br><span class="line">2317</span><br><span class="line">2318</span><br><span class="line">2319</span><br><span class="line">2320</span><br><span class="line">2321</span><br><span class="line">2322</span><br><span class="line">2323</span><br><span class="line">2324</span><br><span class="line">2325</span><br><span class="line">2326</span><br><span class="line">2327</span><br><span class="line">2328</span><br><span class="line">2329</span><br><span class="line">2330</span><br><span class="line">2331</span><br><span class="line">2332</span><br><span class="line">2333</span><br><span class="line">2334</span><br><span class="line">2335</span><br><span class="line">2336</span><br><span class="line">2337</span><br><span class="line">2338</span><br><span class="line">2339</span><br><span class="line">2340</span><br><span class="line">2341</span><br><span class="line">2342</span><br><span class="line">2343</span><br><span class="line">2344</span><br><span class="line">2345</span><br><span class="line">2346</span><br><span class="line">2347</span><br><span class="line">2348</span><br><span class="line">2349</span><br><span class="line">2350</span><br><span class="line">2351</span><br><span class="line">2352</span><br><span class="line">2353</span><br><span class="line">2354</span><br><span class="line">2355</span><br><span class="line">2356</span><br><span class="line">2357</span><br><span class="line">2358</span><br><span class="line">2359</span><br><span class="line">2360</span><br><span class="line">2361</span><br><span class="line">2362</span><br><span class="line">2363</span><br><span class="line">2364</span><br><span class="line">2365</span><br><span class="line">2366</span><br><span class="line">2367</span><br><span class="line">2368</span><br><span class="line">2369</span><br><span class="line">2370</span><br><span class="line">2371</span><br><span class="line">2372</span><br><span class="line">2373</span><br><span class="line">2374</span><br><span class="line">2375</span><br><span class="line">2376</span><br><span class="line">2377</span><br><span class="line">2378</span><br><span class="line">2379</span><br><span class="line">2380</span><br><span class="line">2381</span><br><span class="line">2382</span><br><span class="line">2383</span><br><span class="line">2384</span><br><span class="line">2385</span><br><span class="line">2386</span><br><span class="line">2387</span><br><span class="line">2388</span><br><span class="line">2389</span><br><span class="line">2390</span><br><span class="line">2391</span><br><span class="line">2392</span><br><span class="line">2393</span><br><span class="line">2394</span><br><span class="line">2395</span><br><span class="line">2396</span><br><span class="line">2397</span><br><span class="line">2398</span><br><span class="line">2399</span><br><span class="line">2400</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python3</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="keyword">import</span> math</span><br><span class="line">mList = [<span class="string">'Tom'</span>,<span class="string">'Joy'</span>,<span class="string">'Mal'</span>]</span><br><span class="line">mTuple = (<span class="number">1</span>,<span class="number">2</span>,<span class="string">'Tom'</span>)</span><br><span class="line">mDict = {<span class="string">'Tom'</span>:<span class="number">99</span>,<span class="string">'Joy'</span>:<span class="number">88</span>,<span class="string">'Mal'</span>:<span class="number">77</span>}</span><br><span class="line">mSet = set([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>])</span><br><span class="line">mStr = <span class="string">'ABCD'</span></span><br><span class="line">mInt = int(<span class="number">123</span>)</span><br><span class="line">mGenerator = (x * x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">10</span>))</span><br><span class="line"><span class="comment"># def p(*x):</span></span><br><span class="line"><span class="comment"># for s in x:</span></span><br><span class="line"><span class="comment"># print(s)</span></span><br><span class="line">p = <span class="keyword">print</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">print('hello world')</span><br><span class="line"></span><br><span class="line">1000+1000+2333</span><br><span class="line">print(22+33)</span><br><span class="line">print('100 + 200 =', 100 + 200)</span><br><span class="line">'''</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">用户输入字符串 其中name是变量名可以直接输入name打印变量信息or print(name)</span><br><span class="line"></span><br><span class="line">name = input() </span><br><span class="line">name</span><br><span class="line">print(name)</span><br><span class="line"></span><br><span class="line">name = input('赶快输入的你姓名:')</span><br><span class="line">print('你好啊,',name)</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="string">r'''</span><br><span class="line">print('1024 * 768 = xxx')</span><br><span class="line">print('1024 * 768 = ',1024*768)</span><br><span class="line">'''</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="string">r'''</span><br><span class="line">#print("please input some world:")</span><br><span class="line">a = 100</span><br><span class="line">if a>0:</span><br><span class="line"> print(a)</span><br><span class="line">else:</span><br><span class="line"> print(-a)</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="string">r'''</span><br><span class="line">#打印出I'm "OK" 的写法.转义字符\可以转义很多字符,比如\n表示换行,\t表示制表符,字符\本身也要转义,所以\\表示的字符就是\</span><br><span class="line">print('I\'m "OK"\nI\'m "OK" too')</span><br><span class="line">#如果字符串里面有很多字符都需要转义,就需要加很多\,为了简化,Python还允许用r''表示''内部的字符串默认不转义,可以自己试试</span><br><span class="line">print('\\\t\\')</span><br><span class="line">print(r'\\\t\\')</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#如果字符串内部有很多换行,用\n写在一行里不好阅读,为了简化,Python允许用'''内容内容'''的格式表示多行内容</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#print('''line1</span></span><br><span class="line"><span class="comment">#line2</span></span><br><span class="line"><span class="comment">#line3''')</span></span><br><span class="line"><span class="comment">#好像r'''...'''与'''...'''无法前途使用</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#布尔值写法大小写敏感</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">True</span><br><span class="line">5>3 #True</span><br><span class="line">True or False #True</span><br><span class="line">not True #False</span><br><span class="line">#python中的空值Null,0是有意义的</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#变量在程序中就是用一个变量名表示了,变量名必须是大小写英文、数字和_的组合,且不能用数字开头</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">a=1</span><br><span class="line">t_007='t_007'</span><br><span class="line">true='hahaha'</span><br><span class="line">answer=True</span><br><span class="line">print(answer)</span><br><span class="line">answer=true</span><br><span class="line">print(answer)</span><br><span class="line">#这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。</span><br><span class="line">#静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如Java是静态语言,赋值语句如下(// 表示注释):</span><br><span class="line">int a = 123; // a是整数类型变量</span><br><span class="line">a = "ABC"; // 错误:不能把字符串赋给整型变量</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#常量:但事实上Python根本没有任何机制保证PI不会被改变,</span></span><br><span class="line"><span class="comment">#所以,用全部大写的变量名表示常量只是一个习惯上的用法,如果你一定要改变变量PI的值,也没人能拦住你。</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">PI= 3.14159265359</span><br><span class="line">print(PI)</span><br><span class="line">#除法</span><br><span class="line">print(10/3) #答案:3.33333333333</span><br><span class="line">#底板除,只保留整数位</span><br><span class="line">print(10//3) #答案:3</span><br><span class="line">#余数</span><br><span class="line">print(10%3) #答案:1</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#编码:对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">print(ord('A'),</span><br><span class="line">ord('中'),</span><br><span class="line">chr(66),</span><br><span class="line">chr(25991),'\u4e2d\u6587')</span><br><span class="line">#如果知道字符的整数编码,还可以用十六进制这么写str</span><br><span class="line">print('\u4e2d\u6587') #中文</span><br><span class="line">#由于Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。</span><br><span class="line"></span><br><span class="line">#Python对bytes类型的数据用带b前缀的单引号或双引号表示</span><br><span class="line">x= b'ABC'</span><br><span class="line">#要注意区分'ABC'和b'ABC',前者是str,后者虽然内容显示得和前者一样,但bytes的每个字符都只占用一个字节</span><br><span class="line">#以Unicode表示的str通过encode()方法可以编码为指定的bytes</span><br><span class="line">abc = 'ABC'.encode('ascii') #b'ABC</span><br><span class="line">print(abc)</span><br><span class="line">'中文'.encode('utf-8')</span><br><span class="line">#'中文'.encode('ascii') #含有中文的str无法用ASCII编码,因为中文编码的范围超过了ASCII编码的范围,Python会报错。</span><br><span class="line">#纯英文的str可以用ASCII编码为bytes,内容是一样的,含有中文的str可以用UTF-8编码为bytes。</span><br><span class="line">#在bytes中,无法显示为ASCII字符的字节,用\x##显示。</span><br><span class="line"></span><br><span class="line">#反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法</span><br><span class="line">test = b'ABC'.decode('ascii') #ABC</span><br><span class="line">print(test)</span><br><span class="line"></span><br><span class="line">#字符长度函数len()</span><br><span class="line">print(len('中文'.encode('utf-8')))</span><br><span class="line"></span><br><span class="line">#格式化:最后一个常见的问题是如何输出格式化的字符串。在Python中,采用的格式化方式和C语言是一致的,用%实现</span><br><span class="line">print('hello , %s' %'world') #如果只有一个%?,括号可以省略。</span><br><span class="line">print('Hi, %s, you have $%d.' %('zhangshan',10000))</span><br><span class="line">#%d 整数</span><br><span class="line">#%f 浮点数</span><br><span class="line">#%s 字符串</span><br><span class="line">#%x 十六进制整数</span><br><span class="line">#有些时候,字符串里面的%是一个普通字符怎么办?这个时候就需要转义,用%%来表示一个%</span><br><span class="line">print('growth rate : %d%%' %7)</span><br><span class="line">print('growth rate : 7%')</span><br><span class="line">#格式化整数和浮点数还可以指定是否补0和整数与小数的位数</span><br><span class="line">print('%2d - %02d' %(3,1))</span><br><span class="line">print('%.2f' %3.1415926)</span><br><span class="line"></span><br><span class="line">add = 85 - 72</span><br><span class="line">rate = add/72*100</span><br><span class="line">print('%.1f%%' %rate)</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#list和tuple</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">#要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素</span><br><span class="line">classMates = ['Tom','Patter','Joy']</span><br><span class="line">print(classMates)</span><br><span class="line">print(len(classMates),classMates[0],classMates[2],classMates[-1]</span><br><span class="line"> )</span><br><span class="line">#list是一个可变的有序表,所以,可以往list中追加元素到末尾</span><br><span class="line">classMates.append('Test')</span><br><span class="line">print(classMates)</span><br><span class="line">print(len(classMates),classMates[0],classMates[2],classMates[-1]</span><br><span class="line"> )</span><br><span class="line">#也可以把元素插入到指定的位置,比如索引号为1的位置</span><br><span class="line">classMates.insert(1,'index1')</span><br><span class="line">print(classMates)</span><br><span class="line">#要删除list末尾的元素,用pop()方法</span><br><span class="line">classMates.pop()</span><br><span class="line">print(classMates)</span><br><span class="line">#要删除指定位置的元素,用pop(i)方法,其中i是索引位置</span><br><span class="line">classMates.pop(1)</span><br><span class="line">print(classMates)</span><br><span class="line">#要把某个元素替换成别的元素,可以直接赋值给对应的索引位置</span><br><span class="line">classMates[0] = 'tom'</span><br><span class="line">#list里面的元素的数据类型也可以不同</span><br><span class="line">classMates = ['sss',111,True]</span><br><span class="line">print(classMates)</span><br><span class="line">#list元素也可以是其他list</span><br><span class="line">classMates = ['sss',['ite','ites']]</span><br><span class="line">print(len(classMates),classMates)</span><br><span class="line"></span><br><span class="line">#tuple另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改.</span><br><span class="line">classMates = ('Tom','Patter','Joy')</span><br><span class="line">#现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,</span><br><span class="line">#你可以正常地使用classmates[0],classmates[-1],但不能赋值成另外的元素。</span><br><span class="line">#不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。</span><br><span class="line"></span><br><span class="line">#如果要定义一个空的tuple,可以写成():</span><br><span class="line">t = ()</span><br><span class="line">print(t)</span><br><span class="line">#定义一个元素</span><br><span class="line">t = (1)</span><br><span class="line">print(t)</span><br><span class="line">#定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,</span><br><span class="line">#因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。</span><br><span class="line">#所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义</span><br><span class="line">t = (1,)</span><br><span class="line">print(t)</span><br><span class="line">##可变的tuple</span><br><span class="line">t = ('a', 'b',['A', 'B'])</span><br><span class="line">t[2][0] = 'X'</span><br><span class="line">t[2][1] = 'Y'</span><br><span class="line">print(t)</span><br><span class="line">#表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。</span><br><span class="line">#tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。</span><br><span class="line">#即指向'a',就不能改成指向'b',指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#条件判断</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">temp = input('输入你的年龄吧:\n')</span><br><span class="line">age = int(temp)</span><br><span class="line">if age<16:</span><br><span class="line"> print('你是小学生吗?')</span><br><span class="line"> print('你真的不是小学生吗?')</span><br><span class="line">elif age<30:</span><br><span class="line"> print('小伙子要努力工作啦!')</span><br><span class="line"> print('我会的啦')</span><br><span class="line">else:</span><br><span class="line"> print('生活什么的才是最重要的啦')</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#循环</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">names = ['Tom','Joy','Mal']</span><br><span class="line">for x in names:</span><br><span class="line"> print(x)</span><br><span class="line">print('-------------------------------')</span><br><span class="line">for x in names:</span><br><span class="line"> if x == 'Tom':</span><br><span class="line"> print(x)</span><br><span class="line">#如果要计算1-100的整数之和,从1写到100有点困难,幸好Python提供一个range()函数,可以生成一个整数序列,</span><br><span class="line">#再通过list()函数可以转换为list。比如range(5)生成的序列是从0开始小于5的整数</span><br><span class="line">temp = list(range(5))</span><br><span class="line">print(temp)</span><br><span class="line">#range(101)就可以生成0-100的整数序列,计算如下</span><br><span class="line">sum = 0</span><br><span class="line">for x in range(101):</span><br><span class="line"> sum = sum + x</span><br><span class="line">print(sum)</span><br><span class="line">#第二种循环是while循环,只要条件满足,就不断循环,条件不满足时退出循环。</span><br><span class="line">sum = 0</span><br><span class="line">n = 1</span><br><span class="line">while n<99:</span><br><span class="line"> sum = sum + n</span><br><span class="line"> n = n +2</span><br><span class="line">print(sum)</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#字典dict和set</span></span><br><span class="line"><span class="comment">#Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。</span></span><br><span class="line"><span class="comment">#举个例子,假设要根据同学的名字查找对应的成绩,如果用list实现,需要两个list:</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">names = ['Tom','Joy','Mal']</span><br><span class="line">soures = [99,88,77]</span><br><span class="line">#如果用dict实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。</span><br><span class="line">di = {'Tom':99,'Joy':88,'Mal':77}</span><br><span class="line">print(di['Tom'])</span><br><span class="line">di['Tom'] = 100</span><br><span class="line">print(di['Tom'])</span><br><span class="line">#要避免key不存在的错误,有两种办法,一是通过in判断key是否存在:</span><br><span class="line">print('Test' in di,'Tom' in di)</span><br><span class="line">#二是通过dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value:</span><br><span class="line">print(di.get('Test'))</span><br><span class="line">print(di.get('Test',-1))</span><br><span class="line">#注意:返回None的时候Python的交互式命令行不显示结果。</span><br><span class="line">#要删除一个key,用pop(key)方法,对应的value也会从dict中删除:</span><br><span class="line">di.pop('Tom')</span><br><span class="line">print(di)</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#请务必注意,dict内部存放的顺序和key放入的顺序是没有关系的。</span></span><br><span class="line"><span class="comment">#和list比较,dict有以下几个特点:</span></span><br><span class="line"><span class="comment">#查找和插入的速度极快,不会随着key的增加而增加;</span></span><br><span class="line"><span class="comment">#需要占用大量的内存,内存浪费多。</span></span><br><span class="line"><span class="comment">#而list相反:</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">#所以,dict是用空间来换取时间的一种方法。</span></span><br><span class="line"><span class="comment">#dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。</span></span><br><span class="line"><span class="comment">#这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。</span></span><br><span class="line"><span class="comment">#要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key:</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">#set</span></span><br><span class="line"><span class="comment">#set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">#要创建一个set,需要提供一个list作为输入集合</span><br><span class="line">s = set([1,2,3])</span><br><span class="line">print(s)</span><br><span class="line">s.add(4)</span><br><span class="line">print(s)</span><br><span class="line">s.add(1)</span><br><span class="line">print(s)</span><br><span class="line">s.remove(4)</span><br><span class="line">print(s)</span><br><span class="line"></span><br><span class="line">#再议不可变对象</span><br><span class="line"></span><br><span class="line">#上面我们讲了,str是不变对象,而list是可变对象。</span><br><span class="line"></span><br><span class="line">#对于可变对象,比如list,对list进行操作,list内部的内容是会变化的,比如:</span><br><span class="line">a = ['c','b','a']</span><br><span class="line">a.sort() #对元素进行排序</span><br><span class="line">print(a)</span><br><span class="line"></span><br><span class="line">#而对于不可变对象,比如str,对str进行操作呢:</span><br><span class="line">a = 'abc'</span><br><span class="line">b = a.replace('a','A')</span><br><span class="line">print(b,a)</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#要始终牢记的是,a是变量,而'abc'才是字符串对象!有些时候,我们经常说,对象a的内容是'abc',</span></span><br><span class="line"><span class="comment">#但其实是指,a本身是一个变量,它指向的对象的内容才是'abc'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#函数S=π*r*r</span></span><br><span class="line"><span class="comment">#当代码出现有规律的重复的时候,你就需要当心了,每次写3.14 * x * x不仅很麻烦,而且,如果要把3.14改成3.14159265359的时候,得全部替换。</span></span><br><span class="line"><span class="comment">#有了函数,我们就不再每次写s = 3.14 * x * x,</span></span><br><span class="line"><span class="comment">#而是写成更有意义的函数调用s = area_of_circle(x),而函数area_of_circle本身只需要写一次,就可以多次调用。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#抽象</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">计算数列的和,比如:1 + 2 + 3 + ... + 100,写起来十分不方便,于是数学家发明了求和符号∑,可以把1 + 2 + 3 + ... + 100记作:</span><br><span class="line">100</span><br><span class="line">∑n</span><br><span class="line">n=1</span><br><span class="line">'''</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">#也可以在交互式命令行通过help(abs)查看abs函数的帮助信息。</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">print(abs(100))</span><br><span class="line">print(abs(-100))</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#数据类型转换</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">print(int('123'),</span><br><span class="line">#int('12.35'), 不能直接转换</span><br><span class="line">int(float('12.35')),</span><br><span class="line">float('12.35'),</span><br><span class="line">str(12.3),</span><br><span class="line">bool(1),</span><br><span class="line">bool(''))</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#定义函数</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def my_abs(x):</span><br><span class="line"> if x>0:</span><br><span class="line"> return x</span><br><span class="line"> else:</span><br><span class="line"> return -x</span><br><span class="line">'''</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 class="comment">#如果没有return语句,函数执行完毕后也会返回结果,只是结果为None。</span></span><br><span class="line"><span class="comment">#return None可以简写为return。</span></span><br><span class="line"><span class="comment">#Python交互环境中定义函数时,注意Python会出现...的提示。函数定义结束后需要按两次回车重新回到>>>提示符下</span></span><br><span class="line"><span class="comment">#如果你已经把my_abs()的函数定义保存为abstest.py文件了,那么,可以在该文件的当前目录下启动Python解释器,</span></span><br><span class="line"><span class="comment">#用from abstest import my_abs来导入my_abs()函数,注意abstest是文件名(不含.py扩展名)</span></span><br><span class="line"></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="string">r'''</span><br><span class="line">def nop():</span><br><span class="line"> pass</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#pass语句什么都不做,那有什么用?实际上pass可以用来作为占位符,</span></span><br><span class="line"><span class="comment">#比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#参数检查</span></span><br><span class="line"><span class="comment">#调用函数时,如果参数个数不对,Python解释器会自动检查出来,并抛出TypeError:</span></span><br><span class="line"><span class="comment">#但是如果参数类型不对,Python解释器就无法帮我们检查。</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="string">r'''</span><br><span class="line">import math</span><br><span class="line">def move(x, y, step, angle=0):</span><br><span class="line"> nx = x + step * math.cos(angle)</span><br><span class="line"> ny = y + step * math.sin(angle)</span><br><span class="line"> return nx, ny</span><br><span class="line">x, y = move(100, 100, 60, math.pi / 6)</span><br><span class="line">print(x, y)</span><br><span class="line">print(move(11,33,3,math.pi/6))</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#但其实这只是一种假象,Python函数返回的仍然是单一值</span></span><br><span class="line"><span class="comment">#原来返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,</span></span><br><span class="line"><span class="comment">#而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。</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">#Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数、可变参数和关键字参数,</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">r'''</span><br><span class="line">def power(x):</span><br><span class="line"> return x * x</span><br><span class="line"></span><br><span class="line">def power(x, n):</span><br><span class="line"> s = 1</span><br><span class="line"> while n > 0:</span><br><span class="line"> n = n - 1</span><br><span class="line"> s = s * x</span><br><span class="line"> return s</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#修改后的power(x, n)函数有两个参数:x和n,这两个参数都是位置参数,调用函数时,传入的两个值按照位置顺序依次赋给参数x和n。</span></span><br><span class="line"><span class="comment">#默认参数</span></span><br><span class="line"><span class="comment">#新的power(x, n)函数定义没有问题,但是,旧的调用代码失败了,原因是我们增加了一个参数,导致旧的代码因为缺少一个参数而无法正常调用</span></span><br><span class="line"><span class="comment">#这个时候,默认参数就排上用场了。由于我们经常计算x2,所以,完全可以把第二个参数n的默认值设定为2:</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def power(x, n=2):</span><br><span class="line"> s = 1</span><br><span class="line"> while n > 0:</span><br><span class="line"> n = n - 1</span><br><span class="line"> s = s * x</span><br><span class="line"> return s</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#这样,当我们调用power(5)时,相当于调用power(5, 2)</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#先定义一个函数,传入一个list,添加一个END再返回:</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def add_end(L=[]):</span><br><span class="line"> L.append('END')</span><br><span class="line"> return L</span><br><span class="line">'''</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">#当你正常调用时,结果似乎不错:</span><br><span class="line">add_end([1, 2, 3]) #[1, 2, 3, 'END']</span><br><span class="line">#当你使用默认参数调用时,一开始结果也是对的:</span><br><span class="line">add_end() #['END']</span><br><span class="line">#但是,再次调用add_end()时,结果就不对了: </span><br><span class="line">add_end() #['END', 'END']</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#所以,定义默认参数要牢记一点:默认参数必须指向不变对象!</span></span><br><span class="line"><span class="comment">#要修改上面的例子,我们可以用None这个不变对象来实现:</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def add_end(L=None):</span><br><span class="line"> if L is None:</span><br><span class="line"> L = []</span><br><span class="line"> L.append('END')</span><br><span class="line"> return L</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#可变参数</span></span><br><span class="line"><span class="comment">#在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个</span></span><br><span class="line"><span class="comment">#要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c……作为一个list或tuple传进来,</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def calc(numbers):</span><br><span class="line"> sum = 0</span><br><span class="line"> for x in numbers:</span><br><span class="line"> sum = sum + x*x</span><br><span class="line"> return sum</span><br><span class="line">calc([1,2,3])</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#但是调用的时候,需要先组装出一个list或tuple</span></span><br><span class="line"><span class="comment">#所以,我们把函数的参数改为可变参数:</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def calc(*numbers):</span><br><span class="line"> sum = 0</span><br><span class="line"> for n in numbers:</span><br><span class="line"> sum = sum + n * n</span><br><span class="line"> return sum</span><br><span class="line">calc(1,2,3)</span><br><span class="line">#如果已经有一个list或者tuple,要调用一个可变参数怎么办?</span><br><span class="line">nums = [1, 2, 3]</span><br><span class="line">calc(*nums)</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#关键字参数</span></span><br><span class="line"><span class="comment">#可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。</span></span><br><span class="line"><span class="comment">#而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def person(name, age, **kw):</span><br><span class="line"> print('name:', name, 'age:', age, 'other:', kw)</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#命名关键字参数</span></span><br><span class="line"><span class="comment">#对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查。</span></span><br><span class="line"><span class="comment">#仍以person()函数为例,我们希望检查是否有city和job参数:</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def person(name, age, **kw):</span><br><span class="line"> if 'city' in kw:</span><br><span class="line"> # 有city参数</span><br><span class="line"> pass</span><br><span class="line"> if 'job' in kw:</span><br><span class="line"> # 有job参数</span><br><span class="line"> pass</span><br><span class="line"> print('name:', name, 'age:', age, 'other:', kw)</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#但是调用者仍可以传入不受限制的关键字参数:</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def person(name, age, *, city, job):</span><br><span class="line"> print(name, age, city, job)</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数。</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">person('Jack', 24, city='Beijing', job='Engineer')</span><br><span class="line">#Jack 24 Beijing Engineer</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#参数组合</span></span><br><span class="line"><span class="comment">#在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用,</span></span><br><span class="line"><span class="comment">#除了可变参数无法和命名关键字参数混合。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数/命名关键字参数和关键字参数。</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def f1(a, b, c=0, *args, **kw):</span><br><span class="line"> print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)</span><br><span class="line"></span><br><span class="line">def f2(a, b, c=0, *, d, **kw):</span><br><span class="line"> print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#最神奇的是通过一个tuple和dict,你也可以调用上述函数:</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">args = (1, 2, 3, 4)</span><br><span class="line">kw = {'d': 99, 'x': '#'}</span><br><span class="line">f1(*args, **kw)</span><br><span class="line">a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#所以,对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的</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="string">r'''</span><br><span class="line">def fact(n):</span><br><span class="line"> if n == 1:</span><br><span class="line"> return 1</span><br><span class="line"> return n*n-1</span><br><span class="line">print(fact(99))</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。</span></span><br><span class="line"><span class="comment">#使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,</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">#尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。</span></span><br><span class="line"><span class="comment">#这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#上面的fact(n)函数由于return n * fact(n - 1)引入了乘法表达式,所以就不是尾递归了。</span></span><br><span class="line"><span class="comment">#要改成尾递归方式,需要多一点代码,主要是要把每一步的乘积传入到递归函数中:</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">def fact(n):</span><br><span class="line"> return fact_iter(n, 1)</span><br><span class="line"></span><br><span class="line">def fact_iter(num, product):</span><br><span class="line"> if num == 1:</span><br><span class="line"> return product</span><br><span class="line"> return fact_iter(num - 1, num * product)</span><br><span class="line"></span><br><span class="line">print(fact(5))</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。</span></span><br><span class="line"><span class="comment">#遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。</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">l = mList</span><br><span class="line">print(l)</span><br><span class="line">print(l[<span class="number">0</span>:<span class="number">3</span>])</span><br><span class="line">print(l[<span class="number">0</span>:<span class="number">2</span>])</span><br><span class="line">print(l[-<span class="number">2</span>:-<span class="number">1</span>]) <span class="comment">#支持最后一个节点为-1</span></span><br><span class="line">print(l[:<span class="number">1</span>]) <span class="comment">#默认为0时可以省略</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> x <span class="keyword">in</span> mList:</span><br><span class="line"> print(x)</span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> mStr:</span><br><span class="line"> print(x)</span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> Iterable</span><br><span class="line">print(isinstance(<span class="string">'abc'</span>, Iterable)) <span class="comment"># str是否可迭代</span></span><br><span class="line"><span class="comment">#同时引用了两个变量,在Python里是很常见的</span></span><br><span class="line"><span class="keyword">for</span> x, y <span class="keyword">in</span> [(<span class="number">1</span>, <span class="number">1</span>), (<span class="number">2</span>, <span class="number">4</span>), (<span class="number">3</span>, <span class="number">9</span>)]:</span><br><span class="line"> print(x, y)</span><br><span class="line"><span class="comment">#Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身</span></span><br><span class="line"><span class="keyword">for</span> i,value <span class="keyword">in</span> enumerate(mList):</span><br><span class="line"> print(i,value)</span><br><span class="line"></span><br><span class="line"><span class="comment">#列表生产式</span></span><br><span class="line"><span class="comment">#列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。</span></span><br><span class="line">l = []</span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">10</span>):</span><br><span class="line"> l.append(x)</span><br><span class="line">print(l)</span><br><span class="line"><span class="comment">#2</span></span><br><span class="line">l = []</span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">10</span>):</span><br><span class="line"> l.append(x*x)</span><br><span class="line">print(l)</span><br><span class="line"><span class="comment">#3</span></span><br><span class="line">l = [x*x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">10</span>)]</span><br><span class="line">print(l)</span><br><span class="line"><span class="comment">#4 包含if判断</span></span><br><span class="line">l = [x*x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">10</span>) <span class="keyword">if</span> x % <span class="number">2</span> == <span class="number">0</span> ]</span><br><span class="line">print(l)</span><br><span class="line"><span class="comment">#5 双层循环</span></span><br><span class="line">l=[m + n <span class="keyword">for</span> m <span class="keyword">in</span> <span class="string">'ABC'</span> <span class="keyword">for</span> n <span class="keyword">in</span> <span class="string">'abc'</span>]</span><br><span class="line">print(l)</span><br><span class="line"><span class="comment">#6 运用列表生成式,可以写出非常简洁的代码。例如,列出当前目录下的所有文件和目录名,可以通过一行代码实现</span></span><br><span class="line"><span class="keyword">import</span> os <span class="comment">#导入os模块</span></span><br><span class="line">l = [d <span class="keyword">for</span> d <span class="keyword">in</span> os.listdir(<span class="string">'.'</span>)] <span class="comment"># os.listdir可以列出文件和目录</span></span><br><span class="line"><span class="comment">#7for循环其实可以同时使用两个甚至多个变量,比如dict的items()可以同时迭代key和value:</span></span><br><span class="line"><span class="keyword">for</span> k,v <span class="keyword">in</span> mDict.items():</span><br><span class="line"> print(k,<span class="string">'='</span>,v)</span><br><span class="line"></span><br><span class="line"><span class="comment">#生成器</span></span><br><span class="line"><span class="comment">#通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,</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">#这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。</span></span><br><span class="line"><span class="comment">#要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator</span></span><br><span class="line">l = [x * x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">10</span>)] <span class="comment">#list</span></span><br><span class="line">g = (x * x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">10</span>)) <span class="comment">#generator</span></span><br><span class="line"><span class="comment">#一个一个打印出来,可以通过next()函数获得generator的下一个返回值</span></span><br><span class="line">print(next(mGenerator)) </span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> mGenerator:</span><br><span class="line"> print(x)</span><br><span class="line"><span class="comment">#如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(max)</span>:</span></span><br><span class="line"> n, a, b = <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span></span><br><span class="line"> <span class="keyword">while</span> n<max:</span><br><span class="line"> print(b)</span><br><span class="line"> a, b = b, a + b</span><br><span class="line"> n = n + <span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> <span class="string">'done'</span></span><br><span class="line"><span class="comment">#上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(max)</span>:</span></span><br><span class="line"> n, a, b = <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span></span><br><span class="line"> <span class="keyword">while</span> n<max:</span><br><span class="line"> <span class="keyword">yield</span> b</span><br><span class="line"> a, b = b, a + b</span><br><span class="line"> n = n + <span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> <span class="string">'done'</span></span><br><span class="line"><span class="comment">#这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。</span></span><br><span class="line"><span class="comment">#而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">odd</span><span class="params">()</span>:</span></span><br><span class="line"> print(<span class="string">'step 1'</span>)</span><br><span class="line"> <span class="keyword">yield</span> <span class="number">1</span></span><br><span class="line"> print(<span class="string">'step 2'</span>)</span><br><span class="line"> <span class="keyword">yield</span>(<span class="number">3</span>)</span><br><span class="line"> print(<span class="string">'step 3'</span>)</span><br><span class="line"> <span class="keyword">yield</span>(<span class="number">3</span>)</span><br><span class="line">o = odd()</span><br><span class="line">print(next(o),next(o),next(o))</span><br><span class="line"><span class="comment">#但是用for循环调用generator时,发现拿不到generator的return语句的返回值。</span></span><br><span class="line"><span class="comment">#如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中</span></span><br><span class="line">g = fib(<span class="number">6</span>)</span><br><span class="line"><span class="keyword">while</span> <span class="keyword">True</span>:</span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> x = next(g)</span><br><span class="line"> print(<span class="string">'g:'</span>, x)</span><br><span class="line"> <span class="keyword">except</span> StopIteration <span class="keyword">as</span> e:</span><br><span class="line"> print(<span class="string">'Generator return value:'</span>, e.value)</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#迭代器</span></span><br><span class="line"><span class="comment">#我们已经知道,可以直接作用于for循环的数据类型有以下几种:</span></span><br><span class="line"><span class="comment">#一类是集合数据类型,如list、tuple、dict、set、str等;</span></span><br><span class="line"><span class="comment">#一类是generator,包括生成器和带yield的generator function。</span></span><br><span class="line"><span class="comment">#这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。</span></span><br><span class="line"><span class="comment">#可以使用isinstance()判断一个对象是否是Iterable对象:</span></span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> Iterable</span><br><span class="line">print(isinstance([], Iterable),isinstance(mList,Iterable),isinstance(mStr,Iterable),isinstance(mInt,Iterable))</span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> Iterator</span><br><span class="line">print(isinstance((x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>)), Iterator))</span><br><span class="line">print(isinstance([], Iterator),isinstance(mList,Iterator),isinstance(mStr,Iterator),isinstance(mInt,Iterator))</span><br><span class="line"><span class="comment">#生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。</span></span><br><span class="line"><span class="comment">#把list、dict、str等Iterable变成Iterator可以使用iter()函数</span></span><br><span class="line">print(isinstance(iter([]), Iterator))</span><br><span class="line"><span class="comment">#这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,</span></span><br><span class="line"><span class="comment">#直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,</span></span><br><span class="line"><span class="comment">#只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。</span></span><br><span class="line"><span class="comment">#Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用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="string">'''</span><br><span class="line">函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。</span><br><span class="line"></span><br><span class="line">而函数式编程(请注意多了一个“式”字)——Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。</span><br><span class="line"></span><br><span class="line">我们首先要搞明白计算机(Computer)和计算(Compute)的概念。</span><br><span class="line"></span><br><span class="line">在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。</span><br><span class="line"></span><br><span class="line">而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。</span><br><span class="line"></span><br><span class="line">对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如C语言;越高级的语言,越贴近计算,抽象程度高,执行效率低,比如Lisp语言。</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">Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。</span><br><span class="line">'''</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">abs(-<span class="number">1</span>) <span class="comment">#1</span></span><br><span class="line">abs <span class="comment">#<built-in function abs></span></span><br><span class="line"><span class="comment">#可见,abs(-10)是函数调用,而abs是函数本身。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#要获得函数调用结果,我们可以把结果赋值给变量:</span></span><br><span class="line"><span class="string">'''</span><br><span class="line">f = abs</span><br><span class="line">f(-1) #1</span><br><span class="line"># 函数名也是变量</span><br><span class="line">abs = 10</span><br><span class="line">print(abs(-10))</span><br><span class="line">#Traceback (most recent call last):</span><br><span class="line"># File "<stdin>", line 1, in <module></span><br><span class="line">#TypeError: 'int' object is not callable</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">##注:由于abs函数实际上是定义在__builtin__模块中的,所以要让修改abs变量的指向在其它模块也生效,要用__builtin__.abs = 10。</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</span><span class="params">(x, y, f)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> f(x) + f(y)</span><br><span class="line">print(add(-<span class="number">5</span>, <span class="number">6</span>, abs))</span><br><span class="line"></span><br><span class="line"><span class="comment">#map/reduce</span></span><br><span class="line"><span class="comment">#Python内建了map()和reduce()函数。</span></span><br><span class="line"><span class="comment">#我们先看map。map()函数接收两个参数,一个是函数,一个是Iterable,</span></span><br><span class="line"><span class="comment">#map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f</span><span class="params">(x)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> x * x</span><br><span class="line">r = map(f, [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>])</span><br><span class="line">print(list(r))</span><br><span class="line"><span class="comment">#map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,</span></span><br><span class="line"><span class="comment">#因此通过list()函数让它把整个序列都计算出来并返回一个list。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,</span></span><br><span class="line"><span class="comment">#reduce把结果继续和序列的下一个元素做累积计算,其效果就是:</span></span><br><span class="line"><span class="comment">#reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)</span></span><br><span class="line"><span class="comment">#把序列[1, 3, 5, 7, 9]变换成整数13579</span></span><br><span class="line"><span class="keyword">from</span> functools <span class="keyword">import</span> reduce</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fn</span><span class="params">(x, y)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> x*<span class="number">10</span> + y</span><br><span class="line">print(reduce(fn,[<span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">9</span>]))</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">str2int</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">fn</span><span class="params">(x, y)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> x * <span class="number">10</span> + y</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">char2num</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> {<span class="string">'0'</span>: <span class="number">0</span>, <span class="string">'1'</span>: <span class="number">1</span>, <span class="string">'2'</span>: <span class="number">2</span>, <span class="string">'3'</span>: <span class="number">3</span>, <span class="string">'4'</span>: <span class="number">4</span>, <span class="string">'5'</span>: <span class="number">5</span>, <span class="string">'6'</span>: <span class="number">6</span>, <span class="string">'7'</span>: <span class="number">7</span>, <span class="string">'8'</span>: <span class="number">8</span>, <span class="string">'9'</span>: <span class="number">9</span>}[s]</span><br><span class="line"> <span class="keyword">return</span> reduce(fn, map(char2num, s))</span><br><span class="line"><span class="comment">#还可以用lambda函数进一步简化成:</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">char2num</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> {<span class="string">'0'</span>: <span class="number">0</span>, <span class="string">'1'</span>: <span class="number">1</span>, <span class="string">'2'</span>: <span class="number">2</span>, <span class="string">'3'</span>: <span class="number">3</span>, <span class="string">'4'</span>: <span class="number">4</span>, <span class="string">'5'</span>: <span class="number">5</span>, <span class="string">'6'</span>: <span class="number">6</span>, <span class="string">'7'</span>: <span class="number">7</span>, <span class="string">'8'</span>: <span class="number">8</span>, <span class="string">'9'</span>: <span class="number">9</span>}[s]</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">str2int</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> reduce(<span class="keyword">lambda</span> x, y: x * <span class="number">10</span> + y, map(char2num, s))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">##filter</span></span><br><span class="line"><span class="comment">#Python内建的filter()函数用于过滤序列。</span></span><br><span class="line"><span class="comment">#和map()类似,filter()也接收一个函数和一个序列。和map()不同的时,filter()把传入的函数依次作用于每个元素,</span></span><br><span class="line"><span class="comment">#然后根据返回值是True还是False决定保留还是丢弃该元素。</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">is_old</span><span class="params">(x)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> x % <span class="number">2</span> == <span class="number">1</span></span><br><span class="line">list(filter(is_old, [<span class="number">0</span>,<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="comment">#注意到filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,</span></span><br><span class="line"><span class="comment">#需要用list()函数获得所有结果并返回list。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#sorted</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">#如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,</span></span><br><span class="line"><span class="comment">#因此,比较的过程必须通过函数抽象出来。</span></span><br><span class="line">sorted([<span class="string">'bob'</span>, <span class="string">'about'</span>, <span class="string">'Zoo'</span>, <span class="string">'Credit'</span>])</span><br><span class="line"><span class="comment">#这样,我们给sorted传入key函数,即可实现忽略大小写的排序:</span></span><br><span class="line">sorted([<span class="string">'bob'</span>, <span class="string">'about'</span>, <span class="string">'Zoo'</span>, <span class="string">'Credit'</span>], key=str.lower)</span><br><span class="line"><span class="comment">#要进行反向排序,不必改动key函数,可以传入第三个参数reverse=True:</span></span><br><span class="line">sorted([<span class="string">'bob'</span>, <span class="string">'about'</span>, <span class="string">'Zoo'</span>, <span class="string">'Credit'</span>], key=str.lower, reverse=<span class="keyword">True</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">lazy_sum</span><span class="params">(*args)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">sum</span><span class="params">()</span>:</span></span><br><span class="line"> ax = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> n <span class="keyword">in</span> args:</span><br><span class="line"> ax = ax + n</span><br><span class="line"> <span class="keyword">return</span> ax</span><br><span class="line"> <span class="keyword">return</span> sum</span><br><span class="line">f1 = lazy_sum(<span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">9</span>)</span><br><span class="line"><span class="comment">#print(f1) <function lazy_sum.<locals>.sum at 0x101c6ed90></span></span><br><span class="line"><span class="comment">#调用函数f1时,才真正计算求和的结果:</span></span><br><span class="line">f1()</span><br><span class="line"><span class="comment">#在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,</span></span><br><span class="line"><span class="comment">#当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。</span></span><br><span class="line"><span class="comment">#请再注意一点,当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数:</span></span><br><span class="line">f2 = lazy_sum(<span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">9</span>)</span><br><span class="line">print(f1()==f2())</span><br><span class="line">print(f1==f2)</span><br><span class="line"><span class="comment">#f1()和f2()的调用结果互不影响。</span></span><br><span class="line"><span class="comment">#闭包</span></span><br><span class="line"><span class="comment">#注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,</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">count</span><span class="params">()</span>:</span></span><br><span class="line"> fs = []</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>, <span class="number">4</span>):</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">f</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">return</span> i*i</span><br><span class="line"> fs.append(f)</span><br><span class="line"> <span class="keyword">return</span> fs</span><br><span class="line"></span><br><span class="line">f1, f2, f3 = count()</span><br><span class="line">print(f1(), f2(), f3())</span><br><span class="line"><span class="comment">#全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,</span></span><br><span class="line"><span class="comment">#因此最终结果为9。</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">#已绑定到函数参数的值不变:</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">count</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">f</span><span class="params">(j)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">g</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">return</span> j*j</span><br><span class="line"> <span class="keyword">return</span> g</span><br><span class="line"> fs = []</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>, <span class="number">4</span>):</span><br><span class="line"> fs.append(f(i)) <span class="comment"># f(i)立刻被执行,因此i的当前值被传入f()</span></span><br><span class="line"> <span class="keyword">return</span> fs</span><br><span class="line">f1, f2, f3 = count()</span><br><span class="line">print(f1(), f2(), f3())</span><br><span class="line"><span class="comment">#缺点是代码较长,可利用lambda函数缩短代码。</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">#在Python中,对匿名函数提供了有限支持。还是以map()函数为例,计算f(x)=x*x时,除了定义一个f(x)的函数外,还可以直接传入匿名函数</span></span><br><span class="line">print(list(map(<span class="keyword">lambda</span> x: x * x, [<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 class="number">9</span>])))</span><br><span class="line"><span class="comment">#[1, 4, 9, 16, 25, 36, 49, 64, 81]</span></span><br><span class="line"><span class="comment">#通过对比可以看出,匿名函数lambda x: x * x实际上就是:</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f</span><span class="params">(x)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> x * x</span><br><span class="line"><span class="comment">#关键字lambda表示匿名函数,冒号前面的x表示函数参数。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。</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">f = <span class="keyword">lambda</span> x: x * x</span><br><span class="line">print(f(<span class="number">5</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">build</span><span class="params">(x, y)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">lambda</span>: x * x + y * y</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">now</span><span class="params">()</span>:</span></span><br><span class="line"> print(<span class="string">'2016-01-26'</span>)</span><br><span class="line">f = now</span><br><span class="line">f()</span><br><span class="line"><span class="comment">#函数对象有一个__name__属性,可以拿到函数的名字:</span></span><br><span class="line">print(now.__name__,f.__name__)</span><br><span class="line"><span class="comment">#现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,</span></span><br><span class="line"><span class="comment">#这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">log</span><span class="params">(func)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">wapper</span><span class="params">(*args, **kw)</span>:</span></span><br><span class="line"> print(<span class="string">'call function %s()'</span> %func.__name__)</span><br><span class="line"> <span class="keyword">return</span> func(*args, **kw)</span><br><span class="line"> <span class="keyword">return</span> wapper</span><br><span class="line"><span class="comment">#观察上面的log,因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。我们要借助Python的@语法,</span></span><br><span class="line"><span class="comment">#把decorator置于函数的定义处:</span></span><br><span class="line"><span class="decorator">@log</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">now</span><span class="params">()</span>:</span></span><br><span class="line"> print(<span class="string">'2016-01-26'</span>)</span><br><span class="line">now()</span><br><span class="line"><span class="comment">#把@log放到now()函数的定义处,相当于执行了语句:</span></span><br><span class="line">now = log(now)</span><br><span class="line"><span class="comment">#由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,</span></span><br><span class="line"><span class="comment">#于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#wrapper()函数的参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,</span></span><br><span class="line"><span class="comment">#首先打印日志,再紧接着调用原始函数。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">log</span><span class="params">(text)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">decorator</span><span class="params">(func)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">wrapper</span><span class="params">(*args, **kw)</span>:</span></span><br><span class="line"> print(<span class="string">'%s %s():'</span> % (text, func.__name__))</span><br><span class="line"> <span class="keyword">return</span> func(*args, **kw)</span><br><span class="line"> <span class="keyword">return</span> wrapper</span><br><span class="line"> <span class="keyword">return</span> decorator</span><br><span class="line"><span class="comment">#这个3层嵌套的decorator用法如下:</span></span><br><span class="line"><span class="decorator">@log('execute')</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">now</span><span class="params">()</span>:</span></span><br><span class="line"> print(<span class="string">'2015-3-25'</span>)</span><br><span class="line">now()</span><br><span class="line">print(now.__name__)</span><br><span class="line"><span class="comment">#和两层嵌套的decorator相比,3层嵌套的效果是这样的:</span></span><br><span class="line">now = log(<span class="string">'execute'</span>)(now)</span><br><span class="line"><span class="comment">#因为返回的那个wrapper()函数名字就是'wrapper',所以,需要把原始函数的__name__等属性复制到wrapper()函数中,</span></span><br><span class="line"><span class="comment">#否则,有些依赖函数签名的代码执行就会出错。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#不需要编写wrapper.__name__ = func.__name__这样的代码,Python内置的functools.wraps就是干这个事的,</span></span><br><span class="line"><span class="comment">#所以,一个完整的decorator的写法如下:</span></span><br><span class="line"><span class="keyword">import</span> functools</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">log</span><span class="params">(func)</span>:</span></span><br><span class="line"><span class="decorator"> @functools.wraps(func)</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">wrapper</span><span class="params">(*args, **kw)</span>:</span></span><br><span class="line"> print(<span class="string">'call %s():'</span> % func.__name__)</span><br><span class="line"> <span class="keyword">return</span> func(*args, **kw)</span><br><span class="line"> <span class="keyword">return</span> wrapper</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">log</span><span class="params">(text)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">decorator</span><span class="params">(func)</span>:</span></span><br><span class="line"><span class="decorator"> @functools.wraps(func)</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">wrapper</span><span class="params">(*args, **kw)</span>:</span></span><br><span class="line"> print(<span class="string">'%s %s():'</span> % (text, func.__name__))</span><br><span class="line"> <span class="keyword">return</span> func(*args, **kw)</span><br><span class="line"> <span class="keyword">return</span> wrapper</span><br><span class="line"> <span class="keyword">return</span> decorator</span><br><span class="line"><span class="decorator">@log('execute')</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">now</span><span class="params">()</span>:</span></span><br><span class="line"> print(<span class="string">'2015-3-25'</span>)</span><br><span class="line">now()</span><br><span class="line">print(now.__name__,<span class="string">'sssssss'</span>)</span><br><span class="line"><span class="comment">#只需记住在定义wrapper()的前面加上@functools.wraps(func)即可。有先后顺序之分,装饰器比赛位于函数之前才能起作用</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#偏函数</span></span><br><span class="line"><span class="comment">#Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。</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><br><span class="line"><span class="comment">#int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换:</span></span><br><span class="line">print( int(<span class="string">'12345'</span>))</span><br><span class="line"><span class="comment">#但int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做N进制的转换:</span></span><br><span class="line">print(int(<span class="string">'12345'</span>, base=<span class="number">8</span>))</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">int2</span><span class="params">(x, base=<span class="number">2</span>)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> int(x, base)</span><br><span class="line">print(int2(<span class="string">'1000000'</span>))</span><br><span class="line"><span class="keyword">import</span> functools</span><br><span class="line">int2 = functools.partial(int, base=<span class="number">2</span>)</span><br><span class="line">print(int2(<span class="string">'1000000'</span>))</span><br><span class="line"><span class="comment">#简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,</span></span><br><span class="line"><span class="comment">#调用这个新函数会更简单。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#注意到上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值:</span></span><br><span class="line">print(int2(<span class="string">'1000000'</span>, base=<span class="number">10</span>))</span><br><span class="line"><span class="comment">#</span></span><br><span class="line">max2 = functools.partial(max, <span class="number">10</span>)</span><br><span class="line"><span class="comment">#实际上会把10作为*args的一部分自动加到左边,也就是:</span></span><br><span class="line"></span><br><span class="line">max2(<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><span class="line"></span><br><span class="line">args = (<span class="number">10</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>)</span><br><span class="line">print(max(*args))</span><br><span class="line"><span class="comment">#结果为10。</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><br><span class="line"><span class="comment">#为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,</span></span><br><span class="line"><span class="comment">#很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。</span></span><br><span class="line"><span class="comment">#为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#一个abc.py的文件就是一个名字叫abc的模块,一个xyz.py的文件就是一个名字叫xyz的模块。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#请注意,每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,</span></span><br><span class="line"><span class="comment">#否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py可以是空文件,也可以有Python代码,</span></span><br><span class="line"><span class="comment">#因为__init__.py本身就是一个模块,而它的模块名就是mycompany</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#!/usr/bin/env python3</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">' a test module '</span></span><br><span class="line"></span><br><span class="line">__author__ = <span class="string">'pyl'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span><span class="params">()</span>:</span></span><br><span class="line"> args = sys.argv</span><br><span class="line"> <span class="keyword">if</span> len(args)==<span class="number">1</span>:</span><br><span class="line"> print(<span class="string">'Hello, world!'</span>)</span><br><span class="line"> <span class="keyword">elif</span> len(args)==<span class="number">2</span>:</span><br><span class="line"> print(<span class="string">'Hello, %s!'</span> % args[<span class="number">1</span>])</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">'Too many arguments!'</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__==<span class="string">'__main__'</span>:</span><br><span class="line"> test()</span><br><span class="line"></span><br><span class="line"><span class="comment">#当我们在命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__,</span></span><br><span class="line"><span class="comment">#而如果在其他地方导入该hello模块时,if判断将失败,因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,</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">'''</span><br><span class="line">正常的函数和变量名是公开的(public),可以被直接引用,比如:abc,x123,PI等;</span><br><span class="line"></span><br><span class="line">类似__xxx__这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__,__name__就是特殊变量,hello模块定义的文档注释也可以用特殊变量__doc__访问,我们自己的变量一般不要用这种变量名;</span><br><span class="line"></span><br><span class="line">类似_xxx和__xxx这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc,__abc等;</span><br><span class="line"></span><br><span class="line">之所以我们说,private函数和变量“不应该”被直接引用,而不是“不能”被直接引用,是因为Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量。</span><br><span class="line">'''</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">_private_1</span><span class="params">(name)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> <span class="string">'Hello, %s'</span> % name</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">_private_2</span><span class="params">(name)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> <span class="string">'Hi, %s'</span> % name</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">greeting</span><span class="params">(name)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> len(name) > <span class="number">3</span>:</span><br><span class="line"> <span class="keyword">return</span> _private_1(name)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="keyword">return</span> _private_2(name)</span><br><span class="line"><span class="string">'''</span><br><span class="line">我们在模块里公开greeting()函数,而把内部逻辑用private函数隐藏起来了,这样,</span><br><span class="line">调用greeting()函数不用关心内部的private函数细节,这也是一种非常有用的代码封装和抽象的方法,即:</span><br><span class="line"></span><br><span class="line">外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public。</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#安装第三方库</span></span><br><span class="line"><span class="comment">#,第三方库都会在Python官方的pypi.python.org网站注册,要安装一个第三方库,必须先知道该库的名称,可以在官网或者pypi上搜索,</span></span><br><span class="line"><span class="comment">#比如Pillow的名称叫Pillow,因此,安装Pillow的命令就是:</span></span><br><span class="line"><span class="comment">#pip install Pillow #</span></span><br><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line">im = Image.open(<span class="string">'test.jpg'</span>)</span><br><span class="line">print(im.format, im.size, im.mode)</span><br><span class="line"><span class="comment">#PNG (400, 300) RGB</span></span><br><span class="line">im.thumbnail((<span class="number">200</span>, <span class="number">100</span>))</span><br><span class="line">im.save(<span class="string">'thumb.jpg'</span>, <span class="string">'JPEG'</span>)</span><br><span class="line"><span class="comment">#pip install mysql-connector-python</span></span><br><span class="line"><span class="comment">#Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中</span></span><br><span class="line"></span><br><span class="line">sys.path</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="string">'''</span><br><span class="line">面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。</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">在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。</span><br><span class="line"></span><br><span class="line">我们以一个例子来说明面向过程和面向对象在程序流程上的不同之处。</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment">#假设我们要处理学生的成绩表,为了表示一个学生的成绩,面向过程的程序可以用一个dict表示</span></span><br><span class="line">stu1 = {<span class="string">'name'</span>:<span class="string">'Tom'</span>,<span class="string">'soure'</span>:<span class="number">99</span>}</span><br><span class="line">stu2 = {<span class="string">'name'</span>:<span class="string">'Joy'</span>,<span class="string">'soure'</span>:<span class="number">88</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">print_soure</span><span class="params">(stu)</span>:</span></span><br><span class="line"> print(<span class="string">'%s : %s'</span> % (stu[<span class="string">'name'</span>], stu[<span class="string">'soure'</span>]))</span><br><span class="line">print_soure(stu1)</span><br><span class="line"></span><br><span class="line"><span class="comment">#如果采用面向对象的程序设计思想,我们首选思考的不是程序的执行流程,而是Student这种数据类型应该被视为一个对象,</span></span><br><span class="line"><span class="comment">#这个对象拥有name和score这两个属性(Property)。如果要打印一个学生的成绩,首先必须创建出这个学生对应的对象,</span></span><br><span class="line"><span class="comment">#然后,给对象发一个print_score消息,让对象自己把自己的数据打印出来。</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="string">"""docstring for Student"""</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, soure)</span>:</span></span><br><span class="line"> <span class="comment">#super(Student, self, name, soure).__init__()</span></span><br><span class="line"> self.name = name</span><br><span class="line"> self.soure = soure</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">print_soure</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">'%s : %s'</span> %(self.name, self.soure))</span><br><span class="line">Tom = Student(<span class="string">'Tom'</span>, <span class="number">98</span>)</span><br><span class="line">Tom.print_soure() </span><br><span class="line"></span><br><span class="line"><span class="comment">#类和实例</span></span><br><span class="line"><span class="comment">#面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,</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">Student</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="string">"""docstring for Student"""</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"> super(Student, self).__init__()</span><br><span class="line"></span><br><span class="line">st = Student()</span><br><span class="line">print(st)</span><br><span class="line"><span class="comment">#class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,</span></span><br><span class="line"><span class="comment">#继承的概念我们后面再讲,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。</span></span><br><span class="line"><span class="comment">#由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。</span></span><br><span class="line"><span class="comment">#通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</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, name, score)</span>:</span></span><br><span class="line"> self.name = name</span><br><span class="line"> self.score = score</span><br><span class="line">st = Student(<span class="string">'Tom'</span>,<span class="number">99</span>)</span><br><span class="line">print(st.name,st.score)</span><br><span class="line"></span><br><span class="line"><span class="comment">#数据封装</span></span><br><span class="line"><span class="comment">#面向对象编程的一个重要特点就是数据封装。在上面的Student类中,</span></span><br><span class="line"><span class="comment">#每个实例就拥有各自的name和score这些数据。我们可以通过函数来访问这些数据</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#访问限制</span></span><br><span class="line"><span class="comment">#在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的name、score属性</span></span><br><span class="line">st.name = <span class="string">'Joy'</span></span><br><span class="line">print(st.name,st.score)</span><br><span class="line"><span class="comment">#如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,</span></span><br><span class="line"><span class="comment">#在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="string">"""docstring for Student"""</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, score)</span>:</span></span><br><span class="line"> super(Student, self).__init__()</span><br><span class="line"> self.__name = name</span><br><span class="line"> self.__score = score</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">get_name</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> self.__name</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">get_score</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> self.__score</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">set_score</span><span class="params">(self, score)</span>:</span></span><br><span class="line"> self.__score = score</span><br><span class="line"><span class="comment">#改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name和实例变量.__score了</span></span><br><span class="line">st = Student(<span class="string">'Tom'</span>, <span class="number">99</span>) </span><br><span class="line"><span class="comment">#print(st.__name,st.__score) </span></span><br><span class="line"><span class="comment">#AttributeError: 'Student' object has no attribute '__name' </span></span><br><span class="line">print(st.get_name(),<span class="string">'namessssss'</span>) </span><br><span class="line"><span class="comment">#这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,</span></span><br><span class="line"><span class="comment">#特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名</span></span><br><span class="line"><span class="comment">#双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。</span></span><br><span class="line"><span class="comment">#不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,</span></span><br><span class="line"><span class="comment">#所以,仍然可以通过_Student__name来访问__name变量:</span></span><br><span class="line">print(<span class="string">'我就是这么任性的访问私有变量:'</span>,st._Student__name)</span><br><span class="line"></span><br><span class="line"><span class="comment">#继承与多态</span></span><br><span class="line"><span class="comment">#在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),</span></span><br><span class="line"><span class="comment">#而被继承的class称为基类、父类或超类(Base class、Super class)。</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">'Animal is running...'</span>)</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Dog</span><span class="params">(Animal)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">'Dog is running...'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">eat</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">'Eating meat...'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Cat</span><span class="params">(Animal)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">'Cat is running...'</span>)</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Bird</span><span class="params">(Animal)</span>:</span></span><br><span class="line"> <span class="keyword">pass</span></span><br><span class="line">dog = Dog()</span><br><span class="line">cat = Cat()</span><br><span class="line">bird = Bird()</span><br><span class="line">dog.run()</span><br><span class="line">dog.eat()</span><br><span class="line">cat.run()</span><br><span class="line">bird.run()</span><br><span class="line"><span class="comment">#要理解多态的好处,我们还需要再编写一个函数,这个函数接受一个Animal类型的变量:</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">run_twice</span><span class="params">(animal)</span>:</span></span><br><span class="line"> animal.run()</span><br><span class="line"> animal.run()</span><br><span class="line">run_twice(dog)</span><br><span class="line"><span class="comment">#静态语音与动态语音</span></span><br><span class="line"><span class="comment">#对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。</span></span><br><span class="line"><span class="comment">#对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Timer</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="string">"""docstring for Timer"""</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"> super(Timer, self).__init__()</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">'start.....'</span>)</span><br><span class="line">timer = Timer()</span><br><span class="line">run_twice(timer)</span><br><span class="line"><span class="comment">#这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#Python的“file-like object“就是一种鸭子类型。对真正的文件对象,它有一个read()方法,返回其内容。但是,许多对象,只要有read()方法,</span></span><br><span class="line"><span class="comment">#都被视为“file-like object“。许多函数接收的参数就是“file-like object“,你不一定要传入真正的文件对象,</span></span><br><span class="line"><span class="comment">#完全可以传入任何实现了read()方法的对象 </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">#使用type()</span></span><br><span class="line">print(type(<span class="number">123</span>),type(<span class="string">'123'</span>),type(<span class="keyword">True</span>),type(mList),type(abs))</span><br><span class="line"><span class="comment">#使用isinstance()</span></span><br><span class="line"><span class="comment">#对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。</span></span><br><span class="line">print(isinstance(dog, Dog))</span><br><span class="line">print(isinstance(dog, Animal))</span><br><span class="line">print(isinstance(dog, str))</span><br><span class="line"><span class="comment">#使用dir()</span></span><br><span class="line"><span class="comment">#如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:</span></span><br><span class="line">p(dir(<span class="string">'ABC'</span>))</span><br><span class="line">p(<span class="string">'ABC'</span>.__len__())</span><br><span class="line"></span><br><span class="line"><span class="comment">#仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:</span></span><br><span class="line">hasattr(dog, <span class="string">'x'</span>) <span class="comment"># 有属性'x'吗?</span></span><br><span class="line">setattr(dog, <span class="string">'y'</span>, <span class="number">19</span>) <span class="comment"># 设置一个属性'y'</span></span><br><span class="line">p(getattr(dog, <span class="string">'y'</span>)) <span class="comment"># 获取属性'y'</span></span><br><span class="line">p(dog.y) <span class="comment"># 获取属性'y'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#实例属性和类属性</span></span><br><span class="line"><span class="comment">#由于Python是动态语言,根据类创建的实例可以任意绑定属性。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#给实例绑定属性的方法是通过实例变量,或者通过self变量:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</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, name)</span>:</span></span><br><span class="line"> self.name = name</span><br><span class="line"></span><br><span class="line">s = Student(<span class="string">'Bob'</span>)</span><br><span class="line">s.score = <span class="number">90</span></span><br><span class="line"><span class="comment">#但是,如果Student类本身需要绑定一个属性呢?可以直接在class中定义属性,这种属性是类属性,归Student类所有:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(object)</span>:</span></span><br><span class="line"> name = <span class="string">'Student'</span></span><br><span class="line">st = Student()</span><br><span class="line">p(st.name)</span><br><span class="line">st.name = <span class="string">'Tom'</span></span><br><span class="line">p(st.name)</span><br><span class="line"><span class="keyword">del</span> st.name</span><br><span class="line">p(st.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"></span><br><span class="line"><span class="comment">#面向对象高级编程</span></span><br><span class="line"><span class="comment">#数据封装、继承和多态只是面向对象程序设计中最基础的3个概念。在Python中,面向对象还有很多高级特性,允许我们写出非常强大的功能。</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">#使用__slots__</span></span><br><span class="line"><span class="comment">#正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。先定义class:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="string">"""docstring for Student"""</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"> super(Student, self).__init__()</span><br><span class="line">s = Student()</span><br><span class="line">s.name = <span class="string">'Tom'</span> <span class="comment">#给一个实例绑定属性</span></span><br><span class="line">p(<span class="string">'name:'</span>,s.name) </span><br><span class="line"><span class="keyword">from</span> types <span class="keyword">import</span> MethodType</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">set_name</span><span class="params">(self, name)</span>:</span></span><br><span class="line"> self.name = name</span><br><span class="line">s.set_name = MethodType(set_name, s)<span class="comment"># 给实例绑定一个方法</span></span><br><span class="line">s.set_name(<span class="string">'Joy'</span>)</span><br><span class="line">p(s.name)</span><br><span class="line"><span class="comment">#但是,给一个实例绑定的方法,对另一个实例是不起作用的</span></span><br><span class="line"><span class="comment">#为了给所有实例都绑定方法,可以给class绑定方法:</span></span><br><span class="line">Student.set_name = MethodType(set_name, Student)</span><br><span class="line"><span class="comment">#给class绑定方法后,所有实例均可调用</span></span><br><span class="line"><span class="comment">#使用__slots__</span></span><br><span class="line"><span class="comment">#但是,如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性。</span></span><br><span class="line"><span class="comment">#为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(object)</span>:</span></span><br><span class="line"> __slots__ = (<span class="string">'name'</span>, <span class="string">'age'</span>) <span class="comment"># 用tuple定义允许绑定的属性名称</span></span><br><span class="line"></span><br><span class="line">s = Student()</span><br><span class="line">s.name = <span class="string">'Tom'</span></span><br><span class="line">s.age = <span class="number">24</span></span><br><span class="line"><span class="comment">#s.score = 99</span></span><br><span class="line"><span class="comment">#AttributeError: 'Student' object has no attribute 'score'</span></span><br><span class="line"><span class="comment">#由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GraduateStudent</span><span class="params">(Student)</span>:</span></span><br><span class="line"> <span class="string">"""docstring for GraduateStudent"""</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"> super(GraduateStudent, self).__init__()</span><br><span class="line">s = GraduateStudent()</span><br><span class="line">s.name = <span class="string">'Tom'</span></span><br><span class="line">s.age = <span class="number">24</span></span><br><span class="line">s.score = <span class="number">99</span> </span><br><span class="line">p(s.score)</span><br><span class="line"></span><br><span class="line"><span class="comment">#使用@property</span></span><br><span class="line"><span class="comment">#在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改:</span></span><br><span class="line"><span class="comment">#这显然不合逻辑。为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,</span></span><br><span class="line"><span class="comment">#这样,在set_score()方法里,就可以检查参数</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(object)</span>:</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">get_score</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> self._score</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">set_score</span><span class="params">(self, value)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> isinstance(value, int):</span><br><span class="line"> <span class="keyword">raise</span> ValueError(<span class="string">'score must be an integer!'</span>)</span><br><span class="line"> <span class="keyword">if</span> value < <span class="number">0</span> <span class="keyword">or</span> value > <span class="number">100</span>:</span><br><span class="line"> <span class="keyword">raise</span> ValueError(<span class="string">'score must between 0 ~ 100!'</span>)</span><br><span class="line"> self._score = value</span><br><span class="line">s = Student()</span><br><span class="line">s.set_score(<span class="number">60</span>) <span class="comment"># ok!</span></span><br><span class="line">p(s.get_score())</span><br><span class="line"></span><br><span class="line"><span class="comment">#还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。</span></span><br><span class="line"><span class="comment">#Python内置的@property装饰器就是负责把一个方法变成属性调用的:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(object)</span>:</span></span><br><span class="line"></span><br><span class="line"><span class="decorator"> @property</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">score</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> self._score</span><br><span class="line"></span><br><span class="line"><span class="decorator"> @score.setter</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">score</span><span class="params">(self, value)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> isinstance(value, int):</span><br><span class="line"> <span class="keyword">raise</span> ValueError(<span class="string">'score must be an integer!'</span>)</span><br><span class="line"> <span class="keyword">if</span> value < <span class="number">0</span> <span class="keyword">or</span> value > <span class="number">100</span>:</span><br><span class="line"> <span class="keyword">raise</span> ValueError(<span class="string">'score must between 0 ~ 100!'</span>)</span><br><span class="line"> self._score = value</span><br><span class="line"><span class="comment">#@property的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property就可以了,</span></span><br><span class="line"><span class="comment">#此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作</span></span><br><span class="line">s = Student()</span><br><span class="line">s.score = <span class="number">70</span> <span class="comment"># ok!</span></span><br><span class="line">p(s.score)</span><br><span class="line"></span><br><span class="line"><span class="comment">#多重继承</span></span><br><span class="line"><span class="comment"># Dog - 狗狗;</span></span><br><span class="line"><span class="comment"># Bat - 蝙蝠;</span></span><br><span class="line"><span class="comment"># Parrot - 鹦鹉;</span></span><br><span class="line"><span class="comment"># Ostrich - 鸵鸟。</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Runnable</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">'Running...'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Flyable</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">fly</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">'Flying...'</span>)</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Parrot</span><span class="params">(Flyable, Runnable)</span>:</span></span><br><span class="line"> <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#MixIn</span></span><br><span class="line"><span class="comment"># 在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,</span></span><br><span class="line"><span class="comment"># 比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为MixIn</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"># 看到类似__slots__这种形如__xxx__的变量或者函数名就要注意,这些在Python中是有特殊用途的。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># __slots__我们已经知道怎么用了,__len__()方法我们也知道是为了能让class作用于len()函数。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 除此之外,Python的class中还有许多这样有特殊用途的函数,可以帮助我们定制类。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#__str__</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="string">"""docstring for Student"""</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name)</span>:</span></span><br><span class="line"> super(Student, self).__init__()</span><br><span class="line"> self.name = 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> <span class="string">'Student object (name: %s)'</span> %self.name</span><br><span class="line"> __repr__ = __str__</span><br><span class="line">s = Student(<span class="string">'Tom'</span>)</span><br><span class="line">p(s)</span><br><span class="line"></span><br><span class="line"><span class="comment">#__iter__</span></span><br><span class="line"><span class="comment"># 如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,</span></span><br><span class="line"><span class="comment"># 然后,Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。</span></span><br><span class="line"><span class="comment"># __getitem__</span></span><br><span class="line"><span class="comment"># Fib实例虽然能作用于for循环,看起来和list有点像,但是,把它当成list来使用还是不行,比如,取第5个元素:</span></span><br><span class="line"><span class="comment"># __getattr__</span></span><br><span class="line"><span class="comment"># 正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错。</span></span><br><span class="line"><span class="comment">#要避免这个错误,除了可以加上一个score属性外,Python还有另一个机制,那就是写一个__getattr__()方法,动态返回一个属性。</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Fib</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)</span>:</span></span><br><span class="line"> self.a, self.b = <span class="number">0</span>, <span class="number">1</span> <span class="comment"># 初始化两个计数器a,b</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__iter__</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> self <span class="comment"># 实例本身就是迭代对象,故返回自己</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__next__</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.a, self.b = self.b, self.a + self.b <span class="comment"># 计算下一个值</span></span><br><span class="line"> <span class="keyword">if</span> self.a > <span class="number">100000</span>: <span class="comment"># 退出循环的条件</span></span><br><span class="line"> <span class="keyword">raise</span> StopIteration();</span><br><span class="line"> <span class="keyword">return</span> self.a <span class="comment"># 返回下一个值</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__getitem__</span><span class="params">(self, n)</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> x <span class="keyword">in</span> range(n):</span><br><span class="line"> a, b = b, a + b</span><br><span class="line"> <span class="keyword">return</span> a</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__getattr__</span><span class="params">(self, attr)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> attr==<span class="string">'score'</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="number">99</span></span><br><span class="line"> <span class="keyword">if</span> attr==<span class="string">'age'</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">lambda</span>: <span class="number">25</span></span><br><span class="line"> <span class="keyword">raise</span> AttributeError(<span class="string">'\'Student\' object has no attribute \'%s\''</span> % attr) <span class="comment">#要让class只响应特定的几个属性,抛出AttributeError的错误:</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#利用完全动态的__getattr__,我们可以写出一个链式调用:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Chain</span><span class="params">(object)</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, path=<span class="string">''</span>)</span>:</span></span><br><span class="line"> self._path = path</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__getattr__</span><span class="params">(self, path)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> Chain(<span class="string">'%s/%s'</span> % (self._path, path))</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._path</span><br><span class="line"></span><br><span class="line"> __repr__ = __str__</span><br><span class="line"></span><br><span class="line"><span class="comment"># __call__</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 一个对象实例可以有自己的属性和方法,当我们调用实例方法时,我们用instance.method()来调用。能不能直接在实例本身上调用呢?在Python中,答案是肯定的。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用。请看示例:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</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, name)</span>:</span></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">__call__</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">'My name is %s.'</span> % self.name)</span><br><span class="line"></span><br><span class="line">s = Student(<span class="string">'Michael'</span>)</span><br><span class="line">s()</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">JAN = <span class="number">1</span></span><br><span class="line">FEB = <span class="number">2</span></span><br><span class="line">MAR = <span class="number">3</span></span><br><span class="line">NOV = <span class="number">11</span></span><br><span class="line">DEC = <span class="number">12</span></span><br><span class="line"><span class="comment">#更好的方法是为这样的枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例。Python提供了Enum类来实现这个功能:</span></span><br><span class="line"><span class="keyword">from</span> enum <span class="keyword">import</span> Enum</span><br><span class="line"></span><br><span class="line">Month = Enum(<span class="string">'Month'</span>, (<span class="string">'Jan'</span>, <span class="string">'Feb'</span>, <span class="string">'Mar'</span>, <span class="string">'Apr'</span>, <span class="string">'May'</span>, <span class="string">'Jun'</span>, <span class="string">'Jul'</span>, <span class="string">'Aug'</span>, <span class="string">'Sep'</span>, <span class="string">'Oct'</span>, <span class="string">'Nov'</span>, <span class="string">'Dec'</span>))</span><br><span class="line"><span class="comment">#这样我们就获得了Month类型的枚举类,可以直接使用Month.Jan来引用一个常量,或者枚举它的所有成员:</span></span><br><span class="line"><span class="keyword">for</span> name, member <span class="keyword">in</span> Month.__members__.items():</span><br><span class="line"> print(name, <span class="string">'=>'</span>, member, <span class="string">','</span>, member.value)</span><br><span class="line"></span><br><span class="line"><span class="comment"># value属性则是自动赋给成员的int常量,默认从1开始计数。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果需要更精确地控制枚举类型,可以从Enum派生出自定义类:</span></span><br><span class="line"><span class="keyword">from</span> enum <span class="keyword">import</span> Enum, unique</span><br><span class="line"><span class="decorator">@unique</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Weekday</span><span class="params">(Enum)</span>:</span></span><br><span class="line"> Sun = <span class="number">0</span> <span class="comment"># Sun的value被设定为0</span></span><br><span class="line"> Mon = <span class="number">1</span></span><br><span class="line"> Tue = <span class="number">2</span></span><br><span class="line"> Wed = <span class="number">3</span></span><br><span class="line"> Thu = <span class="number">4</span></span><br><span class="line"> Fri = <span class="number">5</span></span><br><span class="line"> Sat = <span class="number">6</span></span><br><span class="line"><span class="comment">#@unique装饰器可以帮助我们检查保证没有重复值。</span></span><br><span class="line">print(Weekday.Tue)</span><br><span class="line"></span><br><span class="line"><span class="comment">#使用元类</span></span><br><span class="line"><span class="comment">#type()</span></span><br><span class="line"><span class="comment"># 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 比方说我们要定义一个Hello的class,就写一个hello.py模块:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Hello</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">hello</span><span class="params">(self, name=<span class="string">'world'</span>)</span>:</span></span><br><span class="line"> print(<span class="string">'Hello, %s.'</span> % name)</span><br><span class="line"><span class="comment">#当Python解释器载入hello模块时,就会依次执行该模块的所有语句,执行结果就是动态创建出一个Hello的class对象</span></span><br><span class="line"><span class="comment"># type()函数可以查看一个类型或变量的类型,Hello是一个class,它的类型就是type,而h是一个实例,它的类型就是class Hello。</span></span><br><span class="line"><span class="comment"># 我们说class的定义是运行时动态创建的,而创建class的方法就是使用type()函数。</span></span><br><span class="line"><span class="comment"># type()函数既可以返回一个对象的类型,又可以创建出新的类型,</span></span><br><span class="line"><span class="comment"># 比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object)...的定义</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fn</span><span class="params">(self, name=<span class="string">'world'</span>)</span>:</span> <span class="comment"># 先定义函数</span></span><br><span class="line"> print(<span class="string">'Hello, %s.'</span> % name)</span><br><span class="line"></span><br><span class="line">Hello = type(<span class="string">'Hello'</span>, (object,), dict(hello=fn)) <span class="comment"># 创建Hello class</span></span><br><span class="line"></span><br><span class="line">h = Hello()</span><br><span class="line">print(<span class="string">'call h.hello():'</span>)</span><br><span class="line">h.hello()</span><br><span class="line">print(<span class="string">'type(Hello) ='</span>, type(Hello))</span><br><span class="line">print(<span class="string">'type(h) ='</span>, type(h))</span><br><span class="line"></span><br><span class="line"><span class="comment"># metaclass</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># metaclass,直译为元类,简单的解释就是:</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"># 但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 连接起来就是:先定义metaclass,就可以创建类,最后创建实例。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 所以,metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># metaclass是Python面向对象里最难理解,也是最难使用的魔术代码。正常情况下,你不会碰到需要使用metaclass的情况,所以,以下内容看不懂也没关系,因为基本上你不会用到。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 我们先看一个简单的例子,这个metaclass可以给我们自定义的MyList增加一个add方法:</span></span><br><span class="line"><span class="string">' Simple ORM using metaclass '</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Field</span><span class="params">(object)</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, name, column_type)</span>:</span></span><br><span class="line"> self.name = name</span><br><span class="line"> self.column_type = column_type</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> <span class="string">'<%s:%s>'</span> % (self.__class__.__name__, self.name)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StringField</span><span class="params">(Field)</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, name)</span>:</span></span><br><span class="line"> super(StringField, self).__init__(name, <span class="string">'varchar(100)'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IntegerField</span><span class="params">(Field)</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, name)</span>:</span></span><br><span class="line"> super(IntegerField, self).__init__(name, <span class="string">'bigint'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ModelMetaclass</span><span class="params">(type)</span>:</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__new__</span><span class="params">(cls, name, bases, attrs)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> name==<span class="string">'Model'</span>:</span><br><span class="line"> <span class="keyword">return</span> type.__new__(cls, name, bases, attrs)</span><br><span class="line"> print(<span class="string">'Found model: %s'</span> % name)</span><br><span class="line"> mappings = dict()</span><br><span class="line"> <span class="keyword">for</span> k, v <span class="keyword">in</span> attrs.items():</span><br><span class="line"> <span class="keyword">if</span> isinstance(v, Field):</span><br><span class="line"> print(<span class="string">'Found mapping: %s ==> %s'</span> % (k, v))</span><br><span class="line"> mappings[k] = v</span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> mappings.keys():</span><br><span class="line"> attrs.pop(k)</span><br><span class="line"> attrs[<span class="string">'__mappings__'</span>] = mappings <span class="comment"># 保存属性和列的映射关系</span></span><br><span class="line"> attrs[<span class="string">'__table__'</span>] = name <span class="comment"># 假设表名和类名一致</span></span><br><span class="line"> <span class="keyword">return</span> type.__new__(cls, name, bases, attrs)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Model</span><span class="params">(dict, metaclass=ModelMetaclass)</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, **kw)</span>:</span></span><br><span class="line"> super(Model, self).__init__(**kw)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__getattr__</span><span class="params">(self, key)</span>:</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> <span class="keyword">return</span> self[key]</span><br><span class="line"> <span class="keyword">except</span> KeyError:</span><br><span class="line"> <span class="keyword">raise</span> AttributeError(<span class="string">r"'Model' object has no attribute '%s'"</span> % key)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__setattr__</span><span class="params">(self, key, value)</span>:</span></span><br><span class="line"> self[key] = value</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">save</span><span class="params">(self)</span>:</span></span><br><span class="line"> fields = []</span><br><span class="line"> params = []</span><br><span class="line"> args = []</span><br><span class="line"> <span class="keyword">for</span> k, v <span class="keyword">in</span> self.__mappings__.items():</span><br><span class="line"> fields.append(v.name)</span><br><span class="line"> params.append(<span class="string">'?'</span>)</span><br><span class="line"> args.append(getattr(self, k, <span class="keyword">None</span>))</span><br><span class="line"> sql = <span class="string">'insert into %s (%s) values (%s)'</span> % (self.__table__, <span class="string">','</span>.join(fields), <span class="string">','</span>.join(params))</span><br><span class="line"> print(<span class="string">'SQL: %s'</span> % sql)</span><br><span class="line"> print(<span class="string">'ARGS: %s'</span> % str(args))</span><br><span class="line"></span><br><span class="line"><span class="comment"># testing code:</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span><span class="params">(Model)</span>:</span></span><br><span class="line"> id = IntegerField(<span class="string">'id'</span>)</span><br><span class="line"> name = StringField(<span class="string">'username'</span>)</span><br><span class="line"> email = StringField(<span class="string">'email'</span>)</span><br><span class="line"> password = StringField(<span class="string">'password'</span>)</span><br><span class="line"></span><br><span class="line">u = User(id=<span class="number">12345</span>, name=<span class="string">'Michael'</span>, email=<span class="string">'test@orm.org'</span>, password=<span class="string">'my-pwd'</span>)</span><br><span class="line">u.save()</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><br><span class="line"><span class="comment"># 有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修复的。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 有的错误是用户输入造成的,比如让用户输入email地址,结果得到一个空字符串,这种错误可以通过检查用户输入来做相应的处理。</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"># Python内置了一套异常处理机制,来帮助我们进行错误处理。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 此外,我们也需要跟踪程序的执行,查看变量的值是否正确,这个过程称为调试。Python的pdb可以让我们以单步方式执行代码。</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="keyword">try</span>:</span><br><span class="line"> print(<span class="string">'try...'</span>)</span><br><span class="line"> r = <span class="number">10</span> / int(<span class="string">'2'</span>)</span><br><span class="line"> print(<span class="string">'result:'</span>, r)</span><br><span class="line"><span class="keyword">except</span> ValueError <span class="keyword">as</span> e:</span><br><span class="line"> print(<span class="string">'ValueError:'</span>, e)</span><br><span class="line"><span class="keyword">except</span> ZeroDivisionError <span class="keyword">as</span> e:</span><br><span class="line"> print(<span class="string">'ZeroDivisionError:'</span>, e)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">'no error!'</span>)</span><br><span class="line"><span class="keyword">finally</span>:</span><br><span class="line"> print(<span class="string">'finally...'</span>)</span><br><span class="line">print(<span class="string">'END'</span>)</span><br><span class="line"><span class="comment"># 使用try...except捕获错误还有一个巨大的好处,就是可以跨越多层调用,</span></span><br><span class="line"><span class="comment"># 比如函数main()调用foo(),foo()调用bar(),结果bar()出错了,这时,只要main()捕获到了,就可以处理:</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">10</span> / int(s)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">bar</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> foo(s) * <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">main</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> bar(<span class="string">'0'</span>)</span><br><span class="line"> <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line"> print(<span class="string">'Error:'</span>, e)</span><br><span class="line"> <span class="keyword">finally</span>:</span><br><span class="line"> print(<span class="string">'finally...'</span>)</span><br><span class="line"><span class="comment">#调用堆栈</span></span><br><span class="line"><span class="comment"># 如果错误没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误信息,然后程序退出。来看看err.py:</span></span><br><span class="line"><span class="comment"># err.py:</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">10</span> / int(s)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">bar</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> foo(s) * <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">main</span><span class="params">()</span>:</span></span><br><span class="line"> bar(<span class="string">'0'</span>)</span><br><span class="line"></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="comment"># Traceback (most recent call last):</span></span><br><span class="line"><span class="comment"># File "err.py", line 11, in <module></span></span><br><span class="line"><span class="comment"># main()</span></span><br><span class="line"><span class="comment"># File "err.py", line 9, in main</span></span><br><span class="line"><span class="comment"># bar('0')</span></span><br><span class="line"><span class="comment"># File "err.py", line 6, in bar</span></span><br><span class="line"><span class="comment"># return foo(s) * 2</span></span><br><span class="line"><span class="comment"># File "err.py", line 3, in foo</span></span><br><span class="line"><span class="comment"># return 10 / int(s)</span></span><br><span class="line"><span class="comment"># ZeroDivisionError: division by zero</span></span><br><span class="line"><span class="comment"># 根据错误类型ZeroDivisionError,我们判断,int(s)本身并没有出错,但是int(s)返回0,在计算10 / 0时出错,至此,找到错误源头。</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"># 如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了。既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Python内置的logging模块可以非常容易地记录错误信息:</span></span><br><span class="line"><span class="keyword">import</span> logging</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">10</span> / int(s)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">bar</span><span class="params">(s)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> foo(s) * <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">main</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> bar(<span class="string">'0'</span>)</span><br><span class="line"> <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line"> logging.exception(e)</span><br><span class="line"></span><br><span class="line">main()</span><br><span class="line">print(<span class="string">'END'</span>)</span><br><span class="line"><span class="comment"># 样是出错,但程序打印完错误信息后会继续执行,并正常退出:</span></span><br><span class="line"><span class="comment"># ERROR:root:division by zero</span></span><br><span class="line"><span class="comment"># Traceback (most recent call last):</span></span><br><span class="line"><span class="comment"># File "err_logging.py", line 13, in main</span></span><br><span class="line"><span class="comment"># bar('0')</span></span><br><span class="line"><span class="comment"># File "err_logging.py", line 9, in bar</span></span><br><span class="line"><span class="comment"># return foo(s) * 2</span></span><br><span class="line"><span class="comment"># File "err_logging.py", line 6, in foo</span></span><br><span class="line"><span class="comment"># return 10 / int(s)</span></span><br><span class="line"><span class="comment"># ZeroDivisionError: division by zero</span></span><br><span class="line"><span class="comment"># END</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"># 因为错误是class,捕获一个错误就是捕获到该class的一个实例。因此,错误并不是凭空产生的,而是有意创建并抛出的。Python的内置函数会抛出很多类型的错误,我们自己编写的函数也可以抛出错误。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果要抛出错误,首先根据需要,可以定义一个错误的class,选择好继承关系,然后,用raise语句抛出一个错误的实例:</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">FooError</span><span class="params">(ValueError)</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">foo</span><span class="params">(s)</span>:</span></span><br><span class="line"> n = int(s)</span><br><span class="line"> <span class="keyword">if</span> n==<span class="number">0</span>:</span><br><span class="line"> <span class="keyword">raise</span> FooError(<span class="string">'invalid value: %s'</span> % s)</span><br><span class="line"> <span class="keyword">return</span> <span class="number">10</span> / n</span><br><span class="line"></span><br><span class="line"><span class="comment">#foo('0')#TODO</span></span><br><span class="line"><span class="comment"># 执行,可以最后跟踪到我们自己定义的错误:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># $ python3 err_raise.py </span></span><br><span class="line"><span class="comment"># Traceback (most recent call last):</span></span><br><span class="line"><span class="comment"># File "err_throw.py", line 11, in <module></span></span><br><span class="line"><span class="comment"># foo('0')</span></span><br><span class="line"><span class="comment"># File "err_throw.py", line 8, in foo</span></span><br><span class="line"><span class="comment"># raise FooError('invalid value: %s' % s)</span></span><br><span class="line"><span class="comment"># __main__.FooError: invalid value: 0</span></span><br><span class="line"><span class="comment"># 只有在必要的时候才定义我们自己的错误类型。如果可以选择Python已有的内置的错误类型(比如ValueError,TypeError),尽量使用Python内置的错误类型。</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">foo</span><span class="params">(s)</span>:</span></span><br><span class="line"> n = int(s)</span><br><span class="line"> <span class="keyword">if</span> n==<span class="number">0</span>:</span><br><span class="line"> <span class="keyword">raise</span> ValueError(<span class="string">'invalid value: %s'</span> % s)</span><br><span class="line"> <span class="keyword">return</span> <span class="number">10</span> / n</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">bar</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> foo(<span class="string">'0'</span>)</span><br><span class="line"> <span class="keyword">except</span> ValueError <span class="keyword">as</span> e:</span><br><span class="line"> print(<span class="string">'ValueError!'</span>)</span><br><span class="line"> <span class="keyword">raise</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#bar()#TODO</span></span><br><span class="line"><span class="comment"># 在bar()函数中,我们明明已经捕获了错误,但是,打印一个ValueError!后,又把错误通过raise语句抛出去了,这不有病么?</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"># 如果他的老板也处理不了,就一直往上抛,最终会抛给CEO去处理。</span></span><br><span class="line"><span class="comment">#常见错误关系</span></span><br><span class="line"><span class="comment"># BaseException</span></span><br><span class="line"><span class="comment"># +-- SystemExit</span></span><br><span class="line"><span class="comment"># +-- KeyboardInterrupt</span></span><br><span class="line"><span class="comment"># +-- GeneratorExit</span></span><br><span class="line"><span class="comment"># +-- Exception</span></span><br><span class="line"><span class="comment"># +-- StopIteration</span></span><br><span class="line"><span class="comment"># +-- StopAsyncIteration</span></span><br><span class="line"><span class="comment"># +-- ArithmeticError</span></span><br><span class="line"><span class="comment"># | +-- FloatingPointError</span></span><br><span class="line"><span class="comment"># | +-- OverflowError</span></span><br><span class="line"><span class="comment"># | +-- ZeroDivisionError</span></span><br><span class="line"><span class="comment"># +-- AssertionError</span></span><br><span class="line"><span class="comment"># +-- AttributeError</span></span><br><span class="line"><span class="comment"># +-- BufferError</span></span><br><span class="line"><span class="comment"># +-- EOFError</span></span><br><span class="line"><span class="comment"># +-- ImportError</span></span><br><span class="line"><span class="comment"># +-- LookupError</span></span><br><span class="line"><span class="comment"># | +-- IndexError</span></span><br><span class="line"><span class="comment"># | +-- KeyError</span></span><br><span class="line"><span class="comment"># +-- MemoryError</span></span><br><span class="line"><span class="comment"># +-- NameError</span></span><br><span class="line"><span class="comment"># | +-- UnboundLocalError</span></span><br><span class="line"><span class="comment"># +-- OSError</span></span><br><span class="line"><span class="comment"># | +-- BlockingIOError</span></span><br><span class="line"><span class="comment"># | +-- ChildProcessError</span></span><br><span class="line"><span class="comment"># | +-- ConnectionError</span></span><br><span class="line"><span class="comment"># | | +-- BrokenPipeError</span></span><br><span class="line"><span class="comment"># | | +-- ConnectionAbortedError</span></span><br><span class="line"><span class="comment"># | | +-- ConnectionRefusedError</span></span><br><span class="line"><span class="comment"># | | +-- ConnectionResetError</span></span><br><span class="line"><span class="comment"># | +-- FileExistsError</span></span><br><span class="line"><span class="comment"># | +-- FileNotFoundError</span></span><br><span class="line"><span class="comment"># | +-- InterruptedError</span></span><br><span class="line"><span class="comment"># | +-- IsADirectoryError</span></span><br><span class="line"><span class="comment"># | +-- NotADirectoryError</span></span><br><span class="line"><span class="comment"># | +-- PermissionError</span></span><br><span class="line"><span class="comment"># | +-- ProcessLookupError</span></span><br><span class="line"><span class="comment"># | +-- TimeoutError</span></span><br><span class="line"><span class="comment"># +-- ReferenceError</span></span><br><span class="line"><span class="comment"># +-- RuntimeError</span></span><br><span class="line"><span class="comment"># | +-- NotImplementedError</span></span><br><span class="line"><span class="comment"># | +-- RecursionError</span></span><br><span class="line"><span class="comment"># +-- SyntaxError</span></span><br><span class="line"><span class="comment"># | +-- IndentationError</span></span><br><span class="line"><span class="comment"># | +-- TabError</span></span><br><span class="line"><span class="comment"># +-- SystemError</span></span><br><span class="line"><span class="comment"># +-- TypeError</span></span><br><span class="line"><span class="comment"># +-- ValueError</span></span><br><span class="line"><span class="comment"># | +-- UnicodeError</span></span><br><span class="line"><span class="comment"># | +-- UnicodeDecodeError</span></span><br><span class="line"><span class="comment"># | +-- UnicodeEncodeError</span></span><br><span class="line"><span class="comment"># | +-- UnicodeTranslateError</span></span><br><span class="line"><span class="comment"># +-- Warning</span></span><br><span class="line"><span class="comment"># +-- DeprecationWarning</span></span><br><span class="line"><span class="comment"># +-- PendingDeprecationWarning</span></span><br><span class="line"><span class="comment"># +-- RuntimeWarning</span></span><br><span class="line"><span class="comment"># +-- SyntaxWarning</span></span><br><span class="line"><span class="comment"># +-- UserWarning</span></span><br><span class="line"><span class="comment"># +-- FutureWarning</span></span><br><span class="line"><span class="comment"># +-- ImportWarning</span></span><br><span class="line"><span class="comment"># +-- UnicodeWarning</span></span><br><span class="line"><span class="comment"># +-- BytesWarning</span></span><br><span class="line"><span class="comment"># +-- ResourceWarning</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"># 凡是用print()来辅助查看的地方,都可以用断言(assert)来替代:</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(s)</span>:</span></span><br><span class="line"> n = int(s)</span><br><span class="line"> <span class="keyword">assert</span> n != <span class="number">0</span>, <span class="string">'n is zero!'</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">10</span> / n</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line"> foo(<span class="string">'0'</span>)</span><br><span class="line"><span class="comment"># assert的意思是,表达式n != 0应该是True,否则,根据程序运行的逻辑,后面的代码肯定会出错。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果断言失败,assert语句本身就会抛出AssertionError</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># logging</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 把print()替换为logging是第3种方式,和assert比,logging不会抛出错误,而且可以输出到文件:</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> logging</span><br><span class="line">logging.basicConfig(level=logging.INFO)</span><br><span class="line"></span><br><span class="line">s = <span class="string">'0'</span></span><br><span class="line">n = int(s)</span><br><span class="line">logging.info(<span class="string">'n = %d'</span> % n)</span><br><span class="line"><span class="comment">#print(10 / n)</span></span><br><span class="line"><span class="comment"># logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#单元测试</span></span><br><span class="line"><span class="comment"># 为了编写单元测试,我们需要引入Python自带的unittest模块,编写mydict_test.py如下:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># import unittest</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># from mydict import Dict</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># class TestDict(unittest.TestCase):</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def test_init(self):</span></span><br><span class="line"><span class="comment"># d = Dict(a=1, b='test')</span></span><br><span class="line"><span class="comment"># self.assertEqual(d.a, 1)</span></span><br><span class="line"><span class="comment"># self.assertEqual(d.b, 'test')</span></span><br><span class="line"><span class="comment"># self.assertTrue(isinstance(d, dict))</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def test_key(self):</span></span><br><span class="line"><span class="comment"># d = Dict()</span></span><br><span class="line"><span class="comment"># d['key'] = 'value'</span></span><br><span class="line"><span class="comment"># self.assertEqual(d.key, 'value')</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def test_attr(self):</span></span><br><span class="line"><span class="comment"># d = Dict()</span></span><br><span class="line"><span class="comment"># d.key = 'value'</span></span><br><span class="line"><span class="comment"># self.assertTrue('key' in d)</span></span><br><span class="line"><span class="comment"># self.assertEqual(d['key'], 'value')</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def test_keyerror(self):</span></span><br><span class="line"><span class="comment"># d = Dict()</span></span><br><span class="line"><span class="comment"># with self.assertRaises(KeyError):</span></span><br><span class="line"><span class="comment"># value = d['empty']</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def test_attrerror(self):</span></span><br><span class="line"><span class="comment"># d = Dict()</span></span><br><span class="line"><span class="comment"># with self.assertRaises(AttributeError):</span></span><br><span class="line"><span class="comment"># value = d.empty</span></span><br><span class="line"><span class="comment"># 编写单元测试时,我们需要编写一个测试类,从unittest.TestCase继承。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 以test开头的方法就是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 对每一类测试都需要编写一个test_xxx()方法。由于unittest.TestCase提供了很多内置的条件判断,我们只需要调用这些方法就可以断言输出是否是我们所期望的。最常用的断言就是assertEqual():</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># self.assertEqual(abs(-1), 1) # 断言函数返回的结果与1相等</span></span><br><span class="line"><span class="comment"># 另一种重要的断言就是期待抛出指定类型的Error,比如通过d['empty']访问不存在的key时,断言会抛出KeyError:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># with self.assertRaises(KeyError):</span></span><br><span class="line"><span class="comment"># value = d['empty']</span></span><br><span class="line"><span class="comment"># 而通过d.empty访问不存在的key时,我们期待抛出AttributeError:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># with self.assertRaises(AttributeError):</span></span><br><span class="line"><span class="comment"># value = d.empty</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># setUp与tearDown</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 可以在单元测试中编写两个特殊的setUp()和tearDown()方法。这两个方法会分别在每调用一个测试方法的前后分别被执行。</span></span><br><span class="line"></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="comment"># IO编程</span></span><br><span class="line"><span class="comment"># IO在计算机中指Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 比如你打开浏览器,访问新浪首页,浏览器这个程序就需要通过网络IO获取新浪的网页。浏览器首先会发送数据给新浪服务器,告诉它我想要首页的HTML,这个动作是往外发数据,叫Output,随后新浪服务器把网页发过来,这个动作是从外面接收数据,叫Input。所以,通常,程序完成IO操作会有Input和Output两个数据流。当然也有只用一个的情况,比如,从磁盘读取文件到内存,就只有Input操作,反过来,把数据写到磁盘文件里,就只是一个Output操作。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># IO编程中,Stream(流)是一个很重要的概念,可以把流想象成一个水管,数据就是水管里的水,但是只能单向流动。Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。对于浏览网页来说,浏览器和新浪服务器之间至少需要建立两根水管,才可以既能发数据,又能收数据。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 由于CPU和内存的速度远远高于外设的速度,所以,在IO编程中,就存在速度严重不匹配的问题。举个例子来说,比如要把100M的数据写入磁盘,CPU输出100M的数据只需要0.01秒,可是磁盘要接收这100M数据可能需要10秒,怎么办呢?有两种办法:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第一种是CPU等着,也就是程序暂停执行后续代码,等100M的数据在10秒后写入磁盘,再接着往下执行,这种模式称为同步IO;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 另一种方法是CPU不等待,只是告诉磁盘,“您老慢慢写,不着急,我接着干别的事去了”,于是,后续代码可以立刻接着执行,这种模式称为异步IO。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 同步和异步的区别就在于是否等待IO执行的结果。好比你去麦当劳点餐,你说“来个汉堡”,服务员告诉你,对不起,汉堡要现做,需要等5分钟,于是你站在收银台前面等了5分钟,拿到汉堡再去逛商场,这是同步IO。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 你说“来个汉堡”,服务员告诉你,汉堡需要等5分钟,你可以先去逛商场,等做好了,我们再通知你,这样你可以立刻去干别的事情(逛商场),这是异步IO。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 很明显,使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂。想想看,你得知道什么时候通知你“汉堡做好了”,而通知你的方法也各不相同。如果是服务员跑过来找到你,这是回调模式,如果服务员发短信通知你,你就得不停地检查手机,这是轮询模式。总之,异步IO的复杂度远远高于同步IO。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 操作IO的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来方便使用,Python也不例外。我们后面会详细讨论Python的IO编程接口。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 注意,本章的IO编程都是同步模式,异步IO由于复杂度太高,后续涉及到服务器端程序开发时我们再讨论。</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><br><span class="line"><span class="comment"># 前面讲的默认都是读取文本文件,并且是UTF-8编码的文本文件。要读取二进制文件,比如图片、视频等等,用'rb'模式打开文件即可:</span></span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> open(<span class="string">'test.txt'</span>, <span class="string">'w'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> f.write(<span class="string">'今天是 '</span>)</span><br><span class="line"> f.write(datetime.now().strftime(<span class="string">'%Y-%m-%d'</span>))</span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> open(<span class="string">'test.txt'</span>, <span class="string">'r'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> s = f.read()</span><br><span class="line"> print(<span class="string">'open for read...'</span>)</span><br><span class="line"> print(s)</span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> open(<span class="string">'test.txt'</span>, <span class="string">'rb'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> s = f.read()</span><br><span class="line"> print(<span class="string">'open as binary for read...'</span>)</span><br><span class="line"> print(s)</span><br><span class="line"></span><br><span class="line"><span class="comment"># StringIO和BytesIO</span></span><br><span class="line"><span class="comment"># StringIO</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"># StringIO顾名思义就是在内存中读写str。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 要把str写入StringIO,我们需要先创建一个StringIO,然后,像文件一样写入即可:</span></span><br><span class="line"><span class="keyword">from</span> io <span class="keyword">import</span> StringIO</span><br><span class="line"></span><br><span class="line"><span class="comment"># write to StringIO:</span></span><br><span class="line">f = StringIO()</span><br><span class="line">f.write(<span class="string">'hello'</span>)</span><br><span class="line">f.write(<span class="string">' '</span>)</span><br><span class="line">f.write(<span class="string">'world!'</span>)</span><br><span class="line">print(f.getvalue())</span><br><span class="line"></span><br><span class="line"><span class="comment"># read from StringIO:</span></span><br><span class="line">f = StringIO(<span class="string">'水面细风生,\n菱歌慢慢声。\n客亭临小市,\n灯火夜妆明。'</span>)</span><br><span class="line"><span class="keyword">while</span> <span class="keyword">True</span>:</span><br><span class="line"> s = f.readline()</span><br><span class="line"> <span class="keyword">if</span> s == <span class="string">''</span>:</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> print(s.strip())</span><br><span class="line"><span class="comment"># BytesIO</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># BytesIO实现了在内存中读写bytes,我们创建一个BytesIO,然后写入一些bytes:</span></span><br><span class="line"><span class="keyword">from</span> io <span class="keyword">import</span> BytesIO</span><br><span class="line"></span><br><span class="line"><span class="comment"># write to BytesIO:</span></span><br><span class="line">f = BytesIO()</span><br><span class="line">f.write(<span class="string">b'hello'</span>)</span><br><span class="line">f.write(<span class="string">b' '</span>)</span><br><span class="line">f.write(<span class="string">b'world!'</span>)</span><br><span class="line">print(f.getvalue())</span><br><span class="line"></span><br><span class="line"><span class="comment"># read from BytesIO:</span></span><br><span class="line">data = <span class="string">'人闲桂花落,夜静春山空。月出惊山鸟,时鸣春涧中。'</span>.encode(<span class="string">'utf-8'</span>)</span><br><span class="line">f = BytesIO(data)</span><br><span class="line">print(f.read())</span><br><span class="line"></span><br><span class="line"><span class="comment"># 操作文件和目录</span></span><br><span class="line"><span class="comment"># 如果我们要操作文件、目录,可以在命令行下面输入操作系统提供的各种命令来完成。比如dir、cp等命令。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果要在Python程序中执行这些目录和文件的操作怎么办?其实操作系统提供的命令只是简单地调用了操作系统提供的接口函数,Python内置的os模块也可以直接调用操作系统提供的接口函数。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 打开Python交互式命令行,我们来看看如何使用os模块的基本功能:</span></span><br><span class="line"></span><br><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">import</span> os</span><br><span class="line"></span><br><span class="line">pwd = os.path.abspath(<span class="string">'.'</span>)</span><br><span class="line"></span><br><span class="line">print(<span class="string">' Size Last Modified Name'</span>)</span><br><span class="line">print(<span class="string">'------------------------------------------------------------'</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> f <span class="keyword">in</span> os.listdir(pwd):</span><br><span class="line"> fsize = os.path.getsize(f)</span><br><span class="line"> mtime = datetime.fromtimestamp(os.path.getmtime(f)).strftime(<span class="string">'%Y-%m-%d %H:%M'</span>)</span><br><span class="line"> flag = <span class="string">'/'</span> <span class="keyword">if</span> os.path.isdir(f) <span class="keyword">else</span> <span class="string">''</span></span><br><span class="line"> print(<span class="string">'%10d %s %s%s'</span> % (fsize, mtime, f, flag))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 序列化</span></span><br><span class="line"><span class="comment"># 在程序运行的过程中,所有的变量都是在内存中,比如,定义一个dict:</span></span><br><span class="line"></span><br><span class="line">d = dict(name=<span class="string">'Bob'</span>, age=<span class="number">20</span>, score=<span class="number">88</span>)</span><br><span class="line"><span class="comment"># 可以随时修改变量,比如把name改成'Bill',但是一旦程序结束,变量所占用的内存就被操作系统全部回收。如果没有把修改后的'Bill'存储到磁盘上,下次重新运行程序,变量又被初始化为'Bob'。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 我们把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。</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"># 反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Python提供了pickle模块来实现序列化。</span></span><br><span class="line"><span class="keyword">import</span> pickle</span><br><span class="line">d = dict(name=<span class="string">'Tom'</span>, soure=<span class="number">99</span>, age = <span class="number">24</span>)</span><br><span class="line">s = pickle.dumps(d)</span><br><span class="line">p(s)</span><br><span class="line">f = open(<span class="string">'dumps.txt'</span>, <span class="string">'wb'</span>)</span><br><span class="line">pickle.dump(d, f)</span><br><span class="line">f.close()</span><br><span class="line">f = open(<span class="string">'dumps.txt'</span>, <span class="string">'rb'</span>)</span><br><span class="line">d = pickle.load(f)</span><br><span class="line">f.close()</span><br><span class="line">p(d)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># JSON</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># JSON类型 Python类型</span></span><br><span class="line"><span class="comment"># {} dict</span></span><br><span class="line"><span class="comment"># [] list</span></span><br><span class="line"><span class="comment"># "string" str</span></span><br><span class="line"><span class="comment"># 1234.56 int或float</span></span><br><span class="line"><span class="comment"># true/false True/False</span></span><br><span class="line"><span class="comment"># null None</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"></span><br><span class="line">d = dict(name=<span class="string">'Bob'</span>, age=<span class="number">20</span>, score=<span class="number">88</span>)</span><br><span class="line">data = json.dumps(d)</span><br><span class="line">print(<span class="string">'JSON Data is a str:'</span>, data)</span><br><span class="line">reborn = json.loads(data)</span><br><span class="line">print(reborn)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(object)</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, name, age, score)</span>:</span></span><br><span class="line"> self.name = name</span><br><span class="line"> self.age = age</span><br><span class="line"> self.score = score</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> <span class="string">'Student object (%s, %s, %s)'</span> % (self.name, self.age, self.score)</span><br><span class="line"></span><br><span class="line">s = Student(<span class="string">'Bob'</span>, <span class="number">20</span>, <span class="number">88</span>)</span><br><span class="line">std_data = json.dumps(s, default=<span class="keyword">lambda</span> obj: obj.__dict__)</span><br><span class="line">print(<span class="string">'Dump Student:'</span>, std_data)</span><br><span class="line">rebuild = json.loads(std_data, object_hook=<span class="keyword">lambda</span> d: Student(d[<span class="string">'name'</span>], d[<span class="string">'age'</span>], d[<span class="string">'score'</span>]))</span><br><span class="line">print(rebuild)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 进程和线程</span></span><br><span class="line"><span class="comment"># 很多同学都听说过,现代操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 什么叫“多任务”呢?简单地说,就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 现在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 真正的并行执行多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,像Word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。当然,真正地同时执行多线程需要多核CPU才可能实现。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 我们前面编写的所有的Python程序,都是执行单任务的进程,也就是只有一个线程。如果我们要同时执行多个任务怎么办?</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><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><br><span class="line"><span class="comment"># 总结一下就是,多任务的实现有3种方式:</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"># 同时执行多个任务通常各个任务之间并不是没有关联的,而是需要相互通信和协调,有时,任务1必须暂停等待任务2完成后才能继续执行,有时,任务3和任务4又不能同时执行,所以,多进程和多线程的程序的复杂度要远远高于我们前面写的单进程单线程的程序。</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"># Python既支持多进程,又支持多线程,我们会讨论如何编写这两种多任务程序。</span></span><br><span class="line"><span class="comment"># import os</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># print('Process (%s) start...' % os.getpid())</span></span><br><span class="line"><span class="comment"># # Only works on Unix/Linux/Mac:</span></span><br><span class="line"><span class="comment"># pid = os.fork()</span></span><br><span class="line"><span class="comment"># if pid == 0:</span></span><br><span class="line"><span class="comment"># print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))</span></span><br><span class="line"><span class="comment"># else:</span></span><br><span class="line"><span class="comment"># print('I (%s) just created a child process (%s).' % (os.getpid(), pid))</span></span><br><span class="line"><span class="comment"># 运行结果如下:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Process (876) start...</span></span><br><span class="line"><span class="comment"># I (876) just created a child process (877).</span></span><br><span class="line"><span class="comment"># I am child process (877) and my parent is 876.</span></span><br><span class="line"><span class="comment"># 由于Windows没有fork调用,上面的代码在Windows上无法运行。由于Mac系统是基于BSD(Unix的一种)内核,所以,在Mac下运行是没有问题的,推荐大家用Mac学Python!</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># multiprocessing</span></span><br><span class="line"><span class="comment"># 于Python是跨平台的,自然也应该提供一个跨平台的多进程支持。multiprocessing模块就是跨平台版本的多进程模块。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># multiprocessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束</span></span><br><span class="line"><span class="keyword">from</span> multiprocessing <span class="keyword">import</span> Process</span><br><span class="line"><span class="keyword">import</span> os</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_proc</span><span class="params">(name)</span>:</span></span><br><span class="line"> print(<span class="string">'Run Child process name %s(%s)...'</span> %(name, os.getpid()))</span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> print(<span class="string">'Parent Process %s'</span> %os.getpid())</span><br><span class="line"> p = Process(target=run_proc, args = (<span class="string">'test'</span>,))</span><br><span class="line"> print(<span class="string">'Child Process Will start...'</span>)</span><br><span class="line"> p.start()</span><br><span class="line"> p.join()</span><br><span class="line"> print(<span class="string">'Child Process END...'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动,这样创建进程比fork()还要简单。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Pool</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="keyword">from</span> multiprocessing <span class="keyword">import</span> Pool</span><br><span class="line"><span class="keyword">import</span> os, time, random</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">long_time_task</span><span class="params">(name)</span>:</span></span><br><span class="line"> print(<span class="string">"RUn task %s(%s)"</span> %(name, os.getpid()))</span><br><span class="line"> start = time.time()</span><br><span class="line"> time.sleep(random.random() * <span class="number">3</span>)</span><br><span class="line"> end = time.time()</span><br><span class="line"> print(<span class="string">'Task Run %.3f seconds.'</span> %(name, (end - start)))</span><br><span class="line"><span class="keyword">if</span> __name__==<span class="string">'__main__'</span>:</span><br><span class="line"> print(<span class="string">'Parent process %s.'</span> %os.getpid())</span><br><span class="line"> pool = Pool(<span class="number">4</span>)</span><br><span class="line"> <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">5</span>):</span><br><span class="line"> pool.apply_async(long_time_task, args=(x,))</span><br><span class="line"> print(<span class="string">'Waiting for all subprocess done.'</span>)</span><br><span class="line"> pool.close()</span><br><span class="line"> pool.join()</span><br><span class="line"> print(<span class="string">'All subprocess done.'</span>)</span><br><span class="line"><span class="comment"># # 对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 请注意输出的结果,task 0,1,2,3是立刻执行的,而task 4要等待前面某个task完成后才执行,这是因为Pool的默认大小在我的电脑上是4,</span></span><br><span class="line"><span class="comment"># # 因此,最多同时执行4个进程。这是Pool有意设计的限制,并不是操作系统的限制。</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="comment"># # 很多时候,子进程并不是自身,而是一个外部进程。我们创建了子进程后,还需要控制子进程的输入和输出。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # subprocess模块可以让我们非常方便地启动一个子进程,然后控制其输入和输出。</span></span><br><span class="line"><span class="comment"># import subprocess</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># print('$ nslookup www.python.org')</span></span><br><span class="line"><span class="comment"># r = subprocess.call(['nslookup', 'www.python.org'])</span></span><br><span class="line"><span class="comment"># print('Exit code:', r)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># print('$ nslookup')</span></span><br><span class="line"><span class="comment"># p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)</span></span><br><span class="line"><span class="comment"># # output, err = p.communicate(b'set q=mx\npython.org\nexit\n')</span></span><br><span class="line"><span class="comment"># # print(output.decode('utf-8'))</span></span><br><span class="line"><span class="comment"># print('Exit code:', p.returncode)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> subprocess</span><br><span class="line">print(<span class="string">'start...'</span>)</span><br><span class="line">r = subprocess.call([<span class="string">'nslookup'</span>,<span class="string">'www.python.org'</span>])</span><br><span class="line">print(<span class="string">'Exit code:'</span>,r)</span><br><span class="line">p = subprocess.Popen([<span class="string">'nslookup'</span>], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)</span><br><span class="line"><span class="comment"># output, err = p.comunicate(b'set q=mx\npython.org\nexit\n')</span></span><br><span class="line"><span class="comment"># print(output.decode('utf-8'))</span></span><br><span class="line">print(<span class="string">'Exit Code::'</span>,p.returncode)</span><br><span class="line"><span class="comment"># # 进程间通信</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的multiprocessing模块包装了底层的机制,</span></span><br><span class="line"><span class="comment"># # 提供了Queue、Pipes等多种方式来交换数据。</span></span><br><span class="line"><span class="comment"># from multiprocessing import Process, Queue</span></span><br><span class="line"><span class="comment"># import os, time, random</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 写数据进程执行的代码:</span></span><br><span class="line"><span class="comment"># def write(q):</span></span><br><span class="line"><span class="comment"># print('Process to write: %s' % os.getpid())</span></span><br><span class="line"><span class="comment"># for value in ['A', 'B', 'C']:</span></span><br><span class="line"><span class="comment"># print('Put %s to queue...' % value)</span></span><br><span class="line"><span class="comment"># q.put(value)</span></span><br><span class="line"><span class="comment"># time.sleep(random.random())</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 读数据进程执行的代码:</span></span><br><span class="line"><span class="comment"># def read(q):</span></span><br><span class="line"><span class="comment"># print('Process to read: %s' % os.getpid())</span></span><br><span class="line"><span class="comment"># while True:</span></span><br><span class="line"><span class="comment"># value = q.get(True)</span></span><br><span class="line"><span class="comment"># print('Get %s from queue.' % value)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># if __name__=='__main__':</span></span><br><span class="line"><span class="comment"># # 父进程创建Queue,并传给各个子进程:</span></span><br><span class="line"><span class="comment"># q = Queue()</span></span><br><span class="line"><span class="comment"># pw = Process(target=write, args=(q,))</span></span><br><span class="line"><span class="comment"># pr = Process(target=read, args=(q,))</span></span><br><span class="line"><span class="comment"># # 启动子进程pw,写入:</span></span><br><span class="line"><span class="comment"># pw.start()</span></span><br><span class="line"><span class="comment"># # 启动子进程pr,读取:</span></span><br><span class="line"><span class="comment"># pr.start()</span></span><br><span class="line"><span class="comment"># # 等待pw结束:</span></span><br><span class="line"><span class="comment"># pw.join()</span></span><br><span class="line"><span class="comment"># # pr进程里是死循环,无法等待其结束,只能强行终止:</span></span><br><span class="line"><span class="comment"># pr.terminate()</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><br><span class="line"><span class="comment"># # 我们前面提到了进程是由若干线程组成的,一个进程至少有一个线程。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 由于线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行:</span></span><br><span class="line"><span class="comment"># import time, threading</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 新线程执行的代码:</span></span><br><span class="line"><span class="comment"># def loop():</span></span><br><span class="line"><span class="comment"># print('thread %s is running...' % threading.current_thread().name)</span></span><br><span class="line"><span class="comment"># n = 0</span></span><br><span class="line"><span class="comment"># while n < 5:</span></span><br><span class="line"><span class="comment"># n = n + 5 #TODO n = n + 1</span></span><br><span class="line"><span class="comment"># print('thread %s >>> %s' % (threading.current_thread().name, n))</span></span><br><span class="line"><span class="comment"># time.sleep(1)</span></span><br><span class="line"><span class="comment"># print('thread %s ended.' % threading.current_thread().name)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># print('thread %s is running...' % threading.current_thread().name)</span></span><br><span class="line"><span class="comment"># t = threading.Thread(target=loop, name='LoopThread')</span></span><br><span class="line"><span class="comment"># t.start()</span></span><br><span class="line"><span class="comment"># t.join()</span></span><br><span class="line"><span class="comment"># print('thread %s ended.' % threading.current_thread().name)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # Lock</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"># import time, threading</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 假定这是你的银行存款:</span></span><br><span class="line"><span class="comment"># balance = 0</span></span><br><span class="line"><span class="comment"># lock = threading.Lock()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def change_it(n):</span></span><br><span class="line"><span class="comment"># # 先存后取,结果应该为0:</span></span><br><span class="line"><span class="comment"># global balance</span></span><br><span class="line"><span class="comment"># balance = balance + n</span></span><br><span class="line"><span class="comment"># balance = balance - n</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def run_thread(n):</span></span><br><span class="line"><span class="comment"># for i in range(100000):</span></span><br><span class="line"><span class="comment"># # 先要获取锁:</span></span><br><span class="line"><span class="comment"># lock.acquire()</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"># change_it(n)</span></span><br><span class="line"><span class="comment"># finally:</span></span><br><span class="line"><span class="comment"># # 改完了一定要释放锁:</span></span><br><span class="line"><span class="comment"># lock.release()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># t1 = threading.Thread(target=run_thread, args=(5,))</span></span><br><span class="line"><span class="comment"># t2 = threading.Thread(target=run_thread, args=(8,))</span></span><br><span class="line"><span class="comment"># t1.start()</span></span><br><span class="line"><span class="comment"># t2.start()</span></span><br><span class="line"><span class="comment"># t1.join()</span></span><br><span class="line"><span class="comment"># t2.join()</span></span><br><span class="line"><span class="comment"># print(balance)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># # ThreadLocal</span></span><br><span class="line"><span class="comment"># # 全局变量local_school就是一个ThreadLocal对象,每个Thread对它都可以读写student属性,但互不影响。你可以把local_school看成全局变量,</span></span><br><span class="line"><span class="comment"># # 但每个属性如local_school.student都是线程的局部变量,可以任意读写而互不干扰,也不用管理锁的问题,ThreadLocal内部会处理。</span></span><br><span class="line"><span class="comment"># # ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,</span></span><br><span class="line"><span class="comment"># # 这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。</span></span><br><span class="line"><span class="comment"># # 一个ThreadLocal变量虽然是全局变量,但每个线程都只能读写自己线程的独立副本,互不干扰。</span></span><br><span class="line"><span class="comment"># # ThreadLocal解决了参数在一个线程中各个函数之间互相传递的问题。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># import threading</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 创建全局ThreadLocal对象:</span></span><br><span class="line"><span class="comment"># local_school = threading.local()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def process_student():</span></span><br><span class="line"><span class="comment"># # 获取当前线程关联的student:</span></span><br><span class="line"><span class="comment"># std = local_school.student</span></span><br><span class="line"><span class="comment"># print('Hello, %s (in %s)' % (std, threading.current_thread().name))</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># def process_thread(name):</span></span><br><span class="line"><span class="comment"># # 绑定ThreadLocal的student:</span></span><br><span class="line"><span class="comment"># local_school.student = name</span></span><br><span class="line"><span class="comment"># process_student()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')</span></span><br><span class="line"><span class="comment"># t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')</span></span><br><span class="line"><span class="comment"># t1.start()</span></span><br><span class="line"><span class="comment"># t2.start()</span></span><br><span class="line"><span class="comment"># t1.join()</span></span><br><span class="line"><span class="comment"># t2.join()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 分布式进程</span></span><br><span class="line"><span class="comment"># # 在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上。一个服务进程可以作为调度者,将任务分布到其他多个进程中,依靠网络通信。由于managers模块封装很好,不必了解网络通信的细节,就可以很容易地编写分布式多进程程序。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 举个例子:如果我们已经有一个通过Queue通信的多进程程序在同一台机器上运行,现在,由于处理任务的进程任务繁重,希望把发送任务的进程和处理任务的进程分布到两台机器上。怎么用分布式进程实现?</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 原有的Queue可以继续使用,但是,通过managers模块把Queue通过网络暴露出去,就可以让其他机器的进程访问Queue了。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 我们先看服务进程,服务进程负责启动Queue,把Queue注册到网络上,然后往Queue里面写入任务:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># import random, time, queue</span></span><br><span class="line"><span class="comment"># from multiprocessing.managers import BaseManager</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 发送任务的队列:</span></span><br><span class="line"><span class="comment"># task_queue = queue.Queue()</span></span><br><span class="line"><span class="comment"># # 接收结果的队列:</span></span><br><span class="line"><span class="comment"># result_queue = queue.Queue()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 从BaseManager继承的QueueManager:</span></span><br><span class="line"><span class="comment"># class QueueManager(BaseManager):</span></span><br><span class="line"><span class="comment"># pass</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 把两个Queue都注册到网络上, callable参数关联了Queue对象:</span></span><br><span class="line"><span class="comment"># QueueManager.register('get_task_queue', callable=lambda: task_queue)</span></span><br><span class="line"><span class="comment"># QueueManager.register('get_result_queue', callable=lambda: result_queue)</span></span><br><span class="line"><span class="comment"># # 绑定端口5000, 设置验证码'abc':</span></span><br><span class="line"><span class="comment"># manager = QueueManager(address=('', 5000), authkey=b'abc')</span></span><br><span class="line"><span class="comment"># # 启动Queue:</span></span><br><span class="line"><span class="comment"># manager.start()</span></span><br><span class="line"><span class="comment"># # 获得通过网络访问的Queue对象:</span></span><br><span class="line"><span class="comment"># task = manager.get_task_queue()</span></span><br><span class="line"><span class="comment"># result = manager.get_result_queue()</span></span><br><span class="line"><span class="comment"># # 放几个任务进去:</span></span><br><span class="line"><span class="comment"># for i in range(10):</span></span><br><span class="line"><span class="comment"># n = random.randint(0, 10000)</span></span><br><span class="line"><span class="comment"># print('Put task %d...' % n)</span></span><br><span class="line"><span class="comment"># task.put(n)</span></span><br><span class="line"><span class="comment"># # 从result队列读取结果:</span></span><br><span class="line"><span class="comment"># print('Try get results...')</span></span><br><span class="line"><span class="comment"># for i in range(10):</span></span><br><span class="line"><span class="comment"># r = result.get(timeout=10)</span></span><br><span class="line"><span class="comment"># print('Result: %s' % r)</span></span><br><span class="line"><span class="comment"># # 关闭:</span></span><br><span class="line"><span class="comment"># manager.shutdown()</span></span><br><span class="line"><span class="comment"># print('master exit.')</span></span><br><span class="line"><span class="comment"># # 请注意,当我们在一台机器上写多进程程序时,创建的Queue可以直接拿来用,但是,在分布式多进程环境下,</span></span><br><span class="line"><span class="comment"># #添加任务到Queue不可以直接对原始的task_queue进行操作,那样就绕过了QueueManager的封装,</span></span><br><span class="line"><span class="comment"># #必须通过manager.get_task_queue()获得的Queue接口添加。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 然后,在另一台机器上启动任务进程(本机上启动也可以):</span></span><br><span class="line"><span class="comment"># import time, sys, queue</span></span><br><span class="line"><span class="comment"># from multiprocessing.managers import BaseManager</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 创建类似的QueueManager:</span></span><br><span class="line"><span class="comment"># class QueueManager(BaseManager):</span></span><br><span class="line"><span class="comment"># pass</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 由于这个QueueManager只从网络上获取Queue,所以注册时只提供名字:</span></span><br><span class="line"><span class="comment"># QueueManager.register('get_task_queue')</span></span><br><span class="line"><span class="comment"># QueueManager.register('get_result_queue')</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># # 连接到服务器,也就是运行task_master.py的机器:</span></span><br><span class="line"><span class="comment"># server_addr = '127.0.0.1'</span></span><br><span class="line"><span class="comment"># print('Connect to server %s...' % server_addr)</span></span><br><span class="line"><span class="comment"># # 端口和验证码注意保持与task_master.py设置的完全一致:</span></span><br><span class="line"><span class="comment"># m = QueueManager(address=(server_addr, 5000), authkey=b'abc')</span></span><br><span class="line"><span class="comment"># # 从网络连接:</span></span><br><span class="line"><span class="comment"># m.connect()</span></span><br><span class="line"><span class="comment"># # 获取Queue的对象:</span></span><br><span class="line"><span class="comment"># task = m.get_task_queue()</span></span><br><span class="line"><span class="comment"># result = m.get_result_queue()</span></span><br><span class="line"><span class="comment"># # 从task队列取任务,并把结果写入result队列:</span></span><br><span class="line"><span class="comment"># for i in range(10):</span></span><br><span class="line"><span class="comment"># try:</span></span><br><span class="line"><span class="comment"># n = task.get(timeout=1)</span></span><br><span class="line"><span class="comment"># print('run task %d * %d...' % (n, n))</span></span><br><span class="line"><span class="comment"># r = '%d * %d = %d' % (n, n, n*n)</span></span><br><span class="line"><span class="comment"># time.sleep(1)</span></span><br><span class="line"><span class="comment"># result.put(r)</span></span><br><span class="line"><span class="comment"># except Queue.Empty:</span></span><br><span class="line"><span class="comment"># print('task queue is empty.')</span></span><br><span class="line"><span class="comment"># # 处理结束:</span></span><br><span class="line"><span class="comment"># print('worker exit.')</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"># 字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在。比如判断一个字符串是否是合法的Email地址,</span></span><br><span class="line"><span class="comment"># 虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样做不但麻烦,而且代码难以复用</span></span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line">r = re.match(<span class="string">r'^\d{3}\-\d{3,8}$'</span>,<span class="string">'123-1234'</span>)</span><br><span class="line"><span class="keyword">if</span> r:</span><br><span class="line"> print(<span class="string">'success...'</span>)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">'error...'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 切分字符串</span></span><br><span class="line">s = <span class="string">'a b c'</span></span><br><span class="line">print(s.split(<span class="string">' '</span>),re.split(<span class="string">r'\s+'</span>, s))</span><br><span class="line"><span class="comment"># 分组</span></span><br><span class="line"><span class="comment"># 除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组(Group)。比如:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ^(\d{3})-(\d{3,8})$分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码</span></span><br><span class="line">r = re.match(<span class="string">r'^(\d{3})\-(\d{3,8})$'</span>,<span class="string">'159-233333'</span>)</span><br><span class="line">print(r.group(<span class="number">0</span>),r.group(<span class="number">1</span>),r.group(<span class="number">2</span>))</span><br><span class="line"><span class="comment">#注意到group(0)永远是原始字符串,group(1)、group(2)……表示第1、2、……个子串。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 贪婪匹配</span></span><br><span class="line"><span class="comment"># 后需要特别指出的是,正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。举例如下,匹配出数字后面的0</span></span><br><span class="line">print(re.match(<span class="string">r'^(\d+)(0*)$'</span>, <span class="string">'102300'</span>).groups())</span><br><span class="line"><span class="comment"># 必须让\d+采用非贪婪匹配(也就是尽可能少匹配),才能把后面的0匹配出来,加个?就可以让\d+采用非贪婪匹配:</span></span><br><span class="line">print(re.match(<span class="string">r'^(\d+?)(0*)$'</span>, <span class="string">'10200200'</span>).groups())</span><br></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<![CDATA[<h1 id="Python_u5B66_u4E60_281_29"><a href="#Python_u5B66_u4E60_281_29" class="headerlink" title="Python学习(1)"></a>Python学习(1)</h1>]]>
</summary>
<category term="python" scheme="http://www.iwooto.com/tags/python/"/>
</entry>
<entry>
<title><![CDATA[python学习(2)]]></title>
<link href="http://www.iwooto.com/2016/04/06/python%E5%AD%A6%E4%B9%A0-2/"/>
<id>http://www.iwooto.com/2016/04/06/python学习-2/</id>
<published>2016-04-05T17:19:58.000Z</published>
<updated>2016-04-05T17:26:23.752Z</updated>
<content type="html"><![CDATA[<h1 id="Python_u5B66_u4E60_282_29"><a href="#Python_u5B66_u4E60_282_29" class="headerlink" title="Python学习(2)"></a>Python学习(2)</h1><a id="more"></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><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><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><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br><span class="line">554</span><br><span class="line">555</span><br><span class="line">556</span><br><span class="line">557</span><br><span class="line">558</span><br><span class="line">559</span><br><span class="line">560</span><br><span class="line">561</span><br><span class="line">562</span><br><span class="line">563</span><br><span class="line">564</span><br><span class="line">565</span><br><span class="line">566</span><br><span class="line">567</span><br><span class="line">568</span><br><span class="line">569</span><br><span class="line">570</span><br><span class="line">571</span><br><span class="line">572</span><br><span class="line">573</span><br><span class="line">574</span><br><span class="line">575</span><br><span class="line">576</span><br><span class="line">577</span><br><span class="line">578</span><br><span class="line">579</span><br><span class="line">580</span><br><span class="line">581</span><br><span class="line">582</span><br><span class="line">583</span><br><span class="line">584</span><br><span class="line">585</span><br><span class="line">586</span><br><span class="line">587</span><br><span class="line">588</span><br><span class="line">589</span><br><span class="line">590</span><br><span class="line">591</span><br><span class="line">592</span><br><span class="line">593</span><br><span class="line">594</span><br><span class="line">595</span><br><span class="line">596</span><br><span class="line">597</span><br><span class="line">598</span><br><span class="line">599</span><br><span class="line">600</span><br><span class="line">601</span><br><span class="line">602</span><br><span class="line">603</span><br><span class="line">604</span><br><span class="line">605</span><br><span class="line">606</span><br><span class="line">607</span><br><span class="line">608</span><br><span class="line">609</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python3</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="keyword">import</span> hello </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"># datetime</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">import</span> os</span><br><span class="line">print(datetime.now())</span><br><span class="line"><span class="comment">#datetime类型转换为timestamp</span></span><br><span class="line">dt = datetime(<span class="number">2015</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">12</span>, <span class="number">20</span>) <span class="comment"># 用指定日期时间创建datetime</span></span><br><span class="line">st = dt.timestamp()</span><br><span class="line">print(st)</span><br><span class="line"><span class="comment">#timestamp转换为datetime</span></span><br><span class="line">temp = datetime.fromtimestamp(st) <span class="comment"># 本地时间</span></span><br><span class="line">ucttemp = datetime.utcfromtimestamp(st) <span class="comment"># UTC时间</span></span><br><span class="line">print(temp,ucttemp)</span><br><span class="line"><span class="comment"># str转换为datetime</span></span><br><span class="line">cday = datetime.strptime(<span class="string">'2015-6-1 18:19:59'</span>, <span class="string">'%Y-%m-%d %H:%M:%S'</span>)</span><br><span class="line">print(cday)</span><br><span class="line"><span class="comment"># datetime转换为str</span></span><br><span class="line">now = datetime.now()</span><br><span class="line">print(now.strftime(<span class="string">'%Y-%m-%d %H:%M:%S'</span>))</span><br><span class="line"><span class="comment"># datetime加减</span></span><br><span class="line"><span class="comment"># 对日期和时间进行加减实际上就是把datetime往后或往前计算,得到新的datetime。</span></span><br><span class="line"><span class="comment"># 加减可以直接用+和-运算符,不过需要导入timedelta这个类</span></span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime, timedelta</span><br><span class="line">now = now + timedelta(days=<span class="number">2</span>, hours=<span class="number">12</span>)</span><br><span class="line">print(now)</span><br><span class="line"><span class="comment"># 本地时间转换为UTC时间</span></span><br><span class="line"><span class="comment"># 一个datetime类型有一个时区属性tzinfo,但是默认为None,</span></span><br><span class="line"><span class="comment"># 所以无法区分这个datetime到底是哪个时区,除非强行给datetime设置一个时区</span></span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime, timedelta, timezone</span><br><span class="line">tz_utc_8 = timezone(timedelta(hours=<span class="number">8</span>)) <span class="comment"># 创建时区UTC+8:00</span></span><br><span class="line">now = datetime.now()</span><br><span class="line">dt = now.replace(tzinfo=tz_utc_8) <span class="comment"># 强制设置为UTC+8:00</span></span><br><span class="line">print(dt)</span><br><span class="line"><span class="comment"># 我们可以先通过utcnow()拿到当前的UTC时间,再转换为任意时区的时间</span></span><br><span class="line">utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)<span class="comment"># 拿到UTC时间,并强制设置时区为UTC+0:00</span></span><br><span class="line">bj_dt = utc_dt.astimezone(timezone(timedelta(hours=<span class="number">8</span>)))<span class="comment"># astimezone()将转换时区为北京时间</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># collections</span></span><br><span class="line"><span class="comment"># collections是Python内建的一个集合模块,提供了许多有用的集合类。</span></span><br><span class="line"><span class="comment"># namedtuple</span></span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> namedtuple</span><br><span class="line">Point = namedtuple(<span class="string">'Point'</span>, [<span class="string">'x'</span>, <span class="string">'y'</span>])</span><br><span class="line">p = Point(<span class="number">1</span>,<span class="number">2</span>)</span><br><span class="line">print(p.x, p.y)</span><br><span class="line"><span class="comment"># deque</span></span><br><span class="line"><span class="comment"># deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:</span></span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> deque</span><br><span class="line">d = deque([<span class="string">'1'</span>,<span class="number">2</span>,<span class="string">'3'</span>])</span><br><span class="line">d.append(<span class="string">'4'</span>)</span><br><span class="line">print(d)</span><br><span class="line">d.pop()</span><br><span class="line">print(d)</span><br><span class="line">d.appendleft(<span class="string">'0'</span>)</span><br><span class="line">print(d)</span><br><span class="line">d.popleft()</span><br><span class="line">print(d)</span><br><span class="line"><span class="comment"># defaultdict</span></span><br><span class="line"><span class="comment"># 使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict</span></span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> defaultdict</span><br><span class="line">d = defaultdict(<span class="keyword">lambda</span>:<span class="string">'N/A'</span>)</span><br><span class="line">d[<span class="string">'key'</span>] = <span class="string">'val'</span></span><br><span class="line">print(d[<span class="string">'key'</span>])</span><br><span class="line">print(d[<span class="string">'key2'</span>])</span><br><span class="line"><span class="comment"># OrderedDict</span></span><br><span class="line"><span class="comment"># 使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果要保持Key的顺序,可以用OrderedDict,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序</span></span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> OrderedDict</span><br><span class="line">od = OrderedDict()</span><br><span class="line">od[<span class="string">'y'</span>] = <span class="string">'y'</span></span><br><span class="line">od[<span class="string">'x'</span>] = <span class="string">'x'</span></span><br><span class="line">od[<span class="string">'z'</span>] = <span class="string">'z'</span></span><br><span class="line">print(od)</span><br><span class="line"><span class="comment"># OrderedDict可以实现一个FIFO(先进先出)的dict,当容量超出限制时,先删除最早添加的Key</span></span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> OrderedDict</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LastUpdatedOrderedDict</span><span class="params">(OrderedDict)</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, capacity)</span>:</span></span><br><span class="line"> super(LastUpdatedOrderedDict, self).__init__()</span><br><span class="line"> self._capacity = capacity</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__setitem__</span><span class="params">(self, key, value)</span>:</span></span><br><span class="line"> containsKey = <span class="number">1</span> <span class="keyword">if</span> key <span class="keyword">in</span> self <span class="keyword">else</span> <span class="number">0</span></span><br><span class="line"> <span class="keyword">if</span> len(self) - containsKey >= self._capacity:</span><br><span class="line"> last = self.popitem(last=<span class="keyword">False</span>)</span><br><span class="line"> print(<span class="string">'remove:'</span>, last)</span><br><span class="line"> <span class="keyword">if</span> containsKey:</span><br><span class="line"> <span class="keyword">del</span> self[key]</span><br><span class="line"> print(<span class="string">'set:'</span>, (key, value))</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">'add:'</span>, (key, value))</span><br><span class="line"> OrderedDict.__setitem__(self, key, value)</span><br><span class="line"><span class="comment"># Counter</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Counter是一个简单的计数器,例如,统计字符出现的个数</span></span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> Counter</span><br><span class="line">c = Counter()</span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> <span class="string">'abcdefabc'</span>:</span><br><span class="line"> c[x] = c[x] + <span class="number">1</span></span><br><span class="line">print(c)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># base64</span></span><br><span class="line"><span class="comment"># ase64是一种用64个字符来表示任意二进制数据的方法。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 用记事本打开exe、jpg、pdf这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很多无法显示和打印的字符,</span></span><br><span class="line"><span class="comment"># 所以,如果要让记事本这样的文本处理软件能处理二进制数据,就需要一个二进制到字符串的转换方法。</span></span><br><span class="line"><span class="comment"># Base64是一种最常见的二进制编码方法。</span></span><br><span class="line"><span class="comment"># Base64的原理很简单,首先,准备一个包含64个字符的数组:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']</span></span><br><span class="line"><span class="comment"># 然后,对二进制数据进行处理,每3个字节一组,一共是3x8=24bit,划为4组,每组正好6个bit:</span></span><br><span class="line"><span class="comment"># 这样我们得到4个数字作为索引,然后查表,获得相应的4个字符,就是编码后的字符串。</span></span><br><span class="line"><span class="comment"># 所以,Base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%,</span></span><br><span class="line"><span class="comment"># 好处是编码后的文本数据可以在邮件正文、网页等直接显示。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节怎么办?</span></span><br><span class="line"><span class="comment"># Base64用\x00字节在末尾补足后,再在编码的末尾加上1个或2个=号,表示补了多少字节,解码的时候,会自动去掉。</span></span><br><span class="line"><span class="keyword">import</span> base64</span><br><span class="line">print(base64.b64encode(<span class="string">b'A'</span>))</span><br><span class="line">print(base64.b64decode(<span class="string">b'cmluZw=='</span>))</span><br><span class="line"><span class="comment"># 由于标准的Base64编码后可能出现字符+和/,在URL中就不能直接作为参数,</span></span><br><span class="line"><span class="comment"># 所以又有一种"url safe"的base64编码,其实就是把字符+和/分别变成-和_</span></span><br><span class="line">print(base64.b64encode(<span class="string">b'i\xb7\x1d\xfb\xef\xff'</span>))</span><br><span class="line">print(base64.urlsafe_b64encode(<span class="string">b'i\xb7\x1d\xfb\xef\xff'</span>))</span><br><span class="line">print(base64.urlsafe_b64decode(<span class="string">'abcd--__'</span>))</span><br><span class="line"><span class="comment"># Base64是一种通过查表的编码方法,不能用于加密,即使使用自定义的编码表也不行。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Base64适用于小段内容的编码,比如数字证书签名、Cookie的内容等。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># struct</span></span><br><span class="line"><span class="comment"># Python提供了一个struct模块来解决bytes和其他二进制数据类型的转换。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># struct的pack函数把任意数据类型变成bytes</span></span><br><span class="line"><span class="keyword">import</span> struct</span><br><span class="line">b = struct.pack(<span class="string">'>I'</span>, <span class="number">10240099</span>)</span><br><span class="line">print(b)</span><br><span class="line"><span class="comment"># pack的第一个参数是处理指令,'>I'的意思是:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># >表示字节顺序是big-endian,也就是网络序,I表示4字节无符号整数。</span></span><br><span class="line"><span class="comment"># unpack把bytes变成相应的数据类型:</span></span><br><span class="line">struct.unpack(<span class="string">'>IH'</span>, <span class="string">b'\xf0\xf0\xf0\xf0\x80\x80'</span>)</span><br><span class="line"><span class="comment"># 根据>IH的说明,后面的bytes依次变为I:4字节无符号整数和H:2字节无符号整数。</span></span><br><span class="line"><span class="comment"># Windows的位图文件(.bmp)是一种非常简单的文件格式,我们来用struct分析一下。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 首先找一个bmp文件,没有的话用“画图”画一个。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 读入前30个字节来分析:</span></span><br><span class="line"></span><br><span class="line">s = <span class="string">b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00'</span></span><br><span class="line"><span class="comment"># BMP格式采用小端方式存储数据,文件头的结构按顺序如下:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 两个字节:'BM'表示Windows位图,'BA'表示OS/2位图;</span></span><br><span class="line"><span class="comment"># 一个4字节整数:表示位图大小;</span></span><br><span class="line"><span class="comment"># 一个4字节整数:保留位,始终为0;</span></span><br><span class="line"><span class="comment"># 一个4字节整数:实际图像的偏移量;</span></span><br><span class="line"><span class="comment"># 一个4字节整数:Header的字节数;</span></span><br><span class="line"><span class="comment"># 一个4字节整数:图像宽度;</span></span><br><span class="line"><span class="comment"># 一个4字节整数:图像高度;</span></span><br><span class="line"><span class="comment"># 一个2字节整数:始终为1;</span></span><br><span class="line"><span class="comment"># 一个2字节整数:颜色数。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 所以,组合起来用unpack读取:</span></span><br><span class="line"></span><br><span class="line">print(struct.unpack(<span class="string">'<ccIIIIIIHH'</span>, s))</span><br><span class="line"><span class="comment"># (b'B', b'M', 691256, 0, 54, 40, 640, 360, 1, 24)</span></span><br><span class="line"><span class="comment"># 结果显示,b'B'、b'M'说明是Windows位图,位图大小为640x360,颜色数为24。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># hashlib</span></span><br><span class="line"><span class="comment"># 摘要算法简介</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,</span></span><br><span class="line"><span class="comment"># 把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。</span></span><br><span class="line"><span class="keyword">import</span> hashlib</span><br><span class="line">md5 = hashlib.md5()</span><br><span class="line">md5.update(<span class="string">'how to used md5 in python hashlib'</span>.encode(<span class="string">'utf-8'</span>))</span><br><span class="line">md5.update(<span class="string">'how to used md5 in python hashlib too'</span>.encode(<span class="string">'utf-8'</span>))<span class="comment">#more time</span></span><br><span class="line">print(md5.hexdigest())</span><br><span class="line">sha1 = hashlib.sha1()</span><br><span class="line">sha1.update(<span class="string">'how to use sha1 in '</span>.encode(<span class="string">'utf-8'</span>))</span><br><span class="line">sha1.update(<span class="string">'python hashlib?'</span>.encode(<span class="string">'utf-8'</span>))</span><br><span class="line">print(sha1.hexdigest())</span><br><span class="line"></span><br><span class="line"><span class="comment"># itertools</span></span><br><span class="line"><span class="comment"># Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数。</span></span><br><span class="line"><span class="comment"># itertools提供的几个“无限”迭代器:</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> itertools</span><br><span class="line">natuals = itertools.count(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="string">r'''</span><br><span class="line">for x in natuals:</span><br><span class="line"> print(x)</span><br><span class="line">cs = itertools.cycle('ABC') # 注意字符串也是序列的一种</span><br><span class="line">for c in cs:</span><br><span class="line"> print(c)</span><br><span class="line">ns = itertools.repeat('A', 3)</span><br><span class="line">for n in ns:</span><br><span class="line"> print(n)</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment"># 无限序列虽然可以无限迭代下去,但是通常我们会通过takewhile()等函数根据条件判断来截取出一个有限的序列</span></span><br><span class="line">ns = itertools.takewhile(<span class="keyword">lambda</span> x: x <= <span class="number">10</span>, natuals)</span><br><span class="line">print(list(ns))</span><br><span class="line"></span><br><span class="line"><span class="comment"># itertools提供的几个迭代器操作函数chain(),groupby()</span></span><br><span class="line"><span class="comment"># chain()可以把一组迭代对象串联起来,形成一个更大的迭代器</span></span><br><span class="line"><span class="keyword">for</span> c <span class="keyword">in</span> itertools.chain(<span class="string">'ABC'</span>, <span class="string">'XYZ'</span>):</span><br><span class="line"> print(c)</span><br><span class="line"><span class="comment"># 迭代效果:'A' 'B' 'C' 'X' 'Y' 'Z'</span></span><br><span class="line"><span class="comment"># groupby()把迭代器中相邻的重复元素挑出来放在一起</span></span><br><span class="line"><span class="keyword">for</span> key, group <span class="keyword">in</span> itertools.groupby(<span class="string">'AAABBBCCAAA'</span>):</span><br><span class="line"> print(key, list(group))</span><br><span class="line"><span class="comment"># 迭代效果</span></span><br><span class="line"><span class="comment"># A ['A', 'A', 'A']</span></span><br><span class="line"><span class="comment"># B ['B', 'B', 'B']</span></span><br><span class="line"><span class="comment"># C ['C', 'C']</span></span><br><span class="line"><span class="comment"># A ['A', 'A', 'A']</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># XML</span></span><br><span class="line"><span class="comment"># DOM vs SAX</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 操作XML有两种方法:DOM和SAX。DOM会把整个XML读入内存,解析为树,因此占用内存大,解析慢,</span></span><br><span class="line"><span class="comment"># 优点是可以任意遍历树的节点。SAX是流模式,边读边解析,占用内存小,解析快,缺点是我们需要自己处理事件。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 正常情况下,优先考虑SAX,因为DOM实在太占内存。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 在Python中使用SAX解析XML非常简洁,通常我们关心的事件是start_element,end_element和char_data,</span></span><br><span class="line"><span class="comment"># 准备好这3个函数,然后就可以解析xml了。</span></span><br><span class="line"><span class="keyword">from</span> xml.parsers.expat <span class="keyword">import</span> ParserCreate</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DefaultSaxHandler</span><span class="params">(object)</span>:</span></span><br><span class="line"> <span class="string">"""docstring for DefaultSaxHandler"""</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"> super(DefaultSaxHandler, self).__init__()</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">start_element</span><span class="params">(self, name, attrs)</span>:</span></span><br><span class="line"> print(<span class="string">'sax:start_element: %s, attrs: %s'</span> % (name, str(attrs)))</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">end_element</span><span class="params">(self, name)</span>:</span></span><br><span class="line"> print(<span class="string">'sax:end_element: %s'</span> % name)</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">char_data</span><span class="params">(self, text)</span>:</span></span><br><span class="line"> print(<span class="string">'sax:char_data: %s'</span> %text)</span><br><span class="line">xml = <span class="string">r'''<?xml version="1.0"?></span><br><span class="line"><ol></span><br><span class="line"> <li><a href="/python">Python</a></li></span><br><span class="line"> <li><a href="/ruby">Ruby</a></li></span><br><span class="line"></ol></span><br><span class="line">'''</span></span><br><span class="line">handler = DefaultSaxHandler()</span><br><span class="line">parser = ParserCreate()</span><br><span class="line">parser.StartElementHandler = handler.start_element</span><br><span class="line">parser.EndElementHandler = handler.end_element</span><br><span class="line">parser.CharacterDataHandler = handler.char_data</span><br><span class="line">parser.Parse(xml)</span><br><span class="line"><span class="comment"># 需要注意的是读取一大段字符串时,CharacterDataHandler可能被多次调用,</span></span><br><span class="line"><span class="comment">#所以需要自己保存起来,在EndElementHandler里面再合并。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 除了解析XML外,如何生成XML呢?99%的情况下需要生成的XML结构都是非常简单的,</span></span><br><span class="line"><span class="comment">#因此,最简单也是最有效的生成XML的方法是拼接字符串:</span></span><br><span class="line"><span class="comment"># L = []</span></span><br><span class="line"><span class="comment"># L.append(r'<?xml version="1.0"?>')</span></span><br><span class="line"><span class="comment"># L.append(r'<root>')</span></span><br><span class="line"><span class="comment"># L.append(encode('some & data'))</span></span><br><span class="line"><span class="comment"># L.append(r'</root>')</span></span><br><span class="line"><span class="comment">#return ''.join(L)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># HTMLParser</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><br><span class="line"><span class="comment"># 假设第一步已经完成了,第二步应该如何解析HTML呢?</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># HTML本质上是XML的子集,但是HTML的语法没有XML那么严格,所以不能用标准的DOM或SAX来解析HTML。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 好在Python提供了HTMLParser来非常方便地解析HTML,只需简单几行代码</span></span><br><span class="line"><span class="keyword">from</span> html.parser <span class="keyword">import</span> HTMLParser</span><br><span class="line"><span class="keyword">from</span> html.entities <span class="keyword">import</span> name2codepoint</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyHTMLParser</span><span class="params">(HTMLParser)</span>:</span></span><br><span class="line"> <span class="string">"""docstring for MyHTMLParser"""</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"> super(MyHTMLParser, self).__init__()</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">handle_starttag</span><span class="params">(self, tag, attrs)</span>:</span></span><br><span class="line"> print(<span class="string">'<%s>'</span> % tag)</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">handle_endtag</span><span class="params">(self, tag)</span>:</span></span><br><span class="line"> print(<span class="string">'</%s>'</span> % tag)</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">handle_startendtag</span><span class="params">(self, tag, attrs)</span>:</span></span><br><span class="line"> print(<span class="string">'</%s>'</span> % tag)</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">handle_data</span><span class="params">(self, data)</span>:</span></span><br><span class="line"> print(data)</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">handle_comment</span><span class="params">(self, data)</span>:</span></span><br><span class="line"> print(<span class="string">'<!--'</span>, data, <span class="string">'-->'</span>)</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">handle_entityref</span><span class="params">(self, name)</span>:</span></span><br><span class="line"> print(<span class="string">'&%s;'</span> % name)</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">handle_charref</span><span class="params">(self, name)</span>:</span></span><br><span class="line"> print(<span class="string">'&#%s;'</span> % name)</span><br><span class="line">parser = MyHTMLParser()</span><br><span class="line">parser.feed(<span class="string">'''</span><br><span class="line"><html></span><br><span class="line"><head></head></span><br><span class="line"><body></span><br><span class="line"><!-- test html parser --></span><br><span class="line"><p>Some <a href=\"#\">html</a>HTMLtutorial<br>END</p></span><br><span class="line"></body></span><br><span class="line"></html></span><br><span class="line">'''</span>)</span><br><span class="line"><span class="comment"># feed()方法可以多次调用,也就是不一定一次把整个HTML字符串都塞进去,可以一部分一部分塞进去。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 特殊字符有两种,一种是英文表示的&nbsp;,一种是数字表示的&#1234;,这两种字符都可以通过Parser解析出来。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># urllib</span></span><br><span class="line"><span class="comment"># urllib提供了一系列用于操作URL的功能。</span></span><br><span class="line"><span class="comment"># Get</span></span><br><span class="line"><span class="comment"># urllib的request模块可以非常方便地抓取URL内容,也就是发送一个GET请求到指定的页面,然后返回HTTP的响应:</span></span><br><span class="line"><span class="keyword">from</span> urllib <span class="keyword">import</span> request</span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> request.urlopen(<span class="string">'https://api.douban.com/v2/book/2129650'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> data = f.read();</span><br><span class="line"> print(<span class="string">'Status:'</span>,f.status, f.reason)</span><br><span class="line"> <span class="keyword">for</span> k, v <span class="keyword">in</span> f.getheaders():</span><br><span class="line"> print(<span class="string">'%s : %s'</span> % (k, v))</span><br><span class="line"> print(<span class="string">'Data: '</span>,data.decode(<span class="string">'utf-8'</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果我们要想模拟浏览器发送GET请求,就需要使用Request对象,通过往Request对象添加HTTP头,</span></span><br><span class="line"><span class="comment"># 我们就可以把请求伪装成浏览器。例如,模拟iPhone 6去请求豆瓣首页</span></span><br><span class="line"><span class="keyword">from</span> urllib <span class="keyword">import</span> request</span><br><span class="line"></span><br><span class="line">req = request.Request(<span class="string">'http://www.douban.com/'</span>)</span><br><span class="line">req.add_header(<span class="string">'User-Agent'</span>,<span class="string">'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25'</span>)</span><br><span class="line"><span class="keyword">with</span> request.urlopen(req) <span class="keyword">as</span> f:</span><br><span class="line"> print(<span class="string">'Status:'</span>, f.status, f.reason)</span><br><span class="line"> <span class="keyword">for</span> k, v <span class="keyword">in</span> f.getheaders():</span><br><span class="line"> print(<span class="string">'%s: %s'</span> % (k, v))</span><br><span class="line"> print(<span class="string">'Data:'</span>, f.read().decode(<span class="string">'utf-8'</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># Post</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果要以POST发送一个请求,只需要把参数data以bytes形式传入。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 我们模拟一个微博登录,先读取登录的邮箱和口令,然后按照weibo.cn的登录页的格式以username=xxx&password=xxx的编码传入:</span></span><br><span class="line"><span class="keyword">from</span> urllib <span class="keyword">import</span> request, parse</span><br><span class="line"><span class="string">r'''</span><br><span class="line">print('Login to weibo.cn...')</span><br><span class="line">email = input('Email: ')</span><br><span class="line">passwd = input('Password: ')</span><br><span class="line">login_data = parse.urlencode([</span><br><span class="line"> ('username', email),</span><br><span class="line"> ('password', passwd),</span><br><span class="line"> ('entry', 'mweibo'),</span><br><span class="line"> ('client_id', ''),</span><br><span class="line"> ('savestate', '1'),</span><br><span class="line"> ('ec', ''),</span><br><span class="line"> ('pagerefer', 'https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F')</span><br><span class="line">])</span><br><span class="line"></span><br><span class="line">req = request.Request('https://passport.weibo.cn/sso/login')</span><br><span class="line">req.add_header('Origin', 'https://passport.weibo.cn')</span><br><span class="line">req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')</span><br><span class="line">req.add_header('Referer', 'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F')</span><br><span class="line"></span><br><span class="line">with request.urlopen(req, data=login_data.encode('utf-8')) as f:</span><br><span class="line"> print('Status:', f.status, f.reason)</span><br><span class="line"> for k, v in f.getheaders():</span><br><span class="line"> print('%s: %s' % (k, v))</span><br><span class="line"> print('Data:', f.read().decode('utf-8'))</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Handler</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果还需要更复杂的控制,比如通过一个Proxy去访问网站,我们需要利用ProxyHandler来处理,示例代码如下:</span></span><br><span class="line"><span class="comment"># proxy_handler = request.ProxyHandler({'http': 'http://www.example.com:3128/'})</span></span><br><span class="line"><span class="comment"># proxy_auth_handler = request.ProxyBasicAuthHandler()</span></span><br><span class="line"><span class="comment"># proxy_auth_handler.add_password('realm', 'host', 'username', 'password')</span></span><br><span class="line"><span class="comment"># opener = request.build_opener(proxy_handler, proxy_auth_handler)</span></span><br><span class="line"><span class="comment"># with opener.open('http://www.example.com/login.html') as f:</span></span><br><span class="line"><span class="comment"># pass</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">from bs4 import BeautifulSoup</span><br><span class="line">import urllib.request </span><br><span class="line">import urllib.parse</span><br><span class="line">import re</span><br><span class="line">import http.cookiejar</span><br><span class="line">print('第三种方法')</span><br><span class="line">url = 'http://www.baidu.com'</span><br><span class="line">cj = http.cookiejar.CookieJar()</span><br><span class="line">opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))</span><br><span class="line">urllib.request.install_opener(opener)</span><br><span class="line">respones = urllib.request.urlopen(url)</span><br><span class="line">print(respones.getcode())</span><br><span class="line">print(cj)</span><br><span class="line">print(respones.read())</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># PIL</span></span><br><span class="line"><span class="comment"># PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。</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><br><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"></span><br><span class="line"><span class="comment"># 打开一个jpg图像文件,注意是当前路径:</span></span><br><span class="line">im = Image.open(<span class="string">'test.jpg'</span>)</span><br><span class="line"><span class="comment"># 获得图像尺寸:</span></span><br><span class="line">w, h = im.size</span><br><span class="line">print(<span class="string">'Original image size: %sx%s'</span> % (w, h))</span><br><span class="line"><span class="comment"># 缩放到50%:</span></span><br><span class="line">im.thumbnail((w//<span class="number">2</span>, h//<span class="number">2</span>))</span><br><span class="line">print(<span class="string">'Resize image to: %sx%s'</span> % (w//<span class="number">2</span>, h//<span class="number">2</span>))</span><br><span class="line"><span class="comment"># 把缩放后的图像用jpeg格式保存:</span></span><br><span class="line">im.save(<span class="string">'thumbnail.jpg'</span>, <span class="string">'jpeg'</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><br><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image, ImageFilter</span><br><span class="line"></span><br><span class="line"><span class="comment"># 打开一个jpg图像文件,注意是当前路径:</span></span><br><span class="line">im = Image.open(<span class="string">'test.jpg'</span>)</span><br><span class="line"><span class="comment"># 应用模糊滤镜:</span></span><br><span class="line">im2 = im.filter(ImageFilter.BLUR)</span><br><span class="line">im2.save(<span class="string">'blur.jpg'</span>, <span class="string">'jpeg'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># PIL的ImageDraw提供了一系列绘图方法,让我们可以直接绘图。比如要生成字母验证码图片:</span></span><br><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image, ImageDraw, ImageFont, ImageFilter</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> random</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">rndChar</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">return</span> chr(random.randint(<span class="number">65</span>, <span class="number">90</span>))</span><br><span class="line"></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">rndColor</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">return</span> (random.randint(<span class="number">64</span>, <span class="number">255</span>), random.randint(<span class="number">64</span>, <span class="number">255</span>), random.randint(<span class="number">64</span>, <span class="number">255</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 随机颜色2:</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">rndColor2</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">return</span> (random.randint(<span class="number">32</span>, <span class="number">127</span>), random.randint(<span class="number">32</span>, <span class="number">127</span>), random.randint(<span class="number">32</span>, <span class="number">127</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 240 x 60:</span></span><br><span class="line">width = <span class="number">60</span> * <span class="number">4</span></span><br><span class="line">height = <span class="number">60</span></span><br><span class="line">image = Image.new(<span class="string">'RGB'</span>, (width, height), (<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>))</span><br><span class="line"><span class="comment"># 创建Font对象:</span></span><br><span class="line">font = ImageFont.truetype(<span class="string">'C:/Windows/Fonts/Arial.ttf'</span>, <span class="number">36</span>)</span><br><span class="line"><span class="comment"># 创建Draw对象:</span></span><br><span class="line">draw = ImageDraw.Draw(image)</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> range(width):</span><br><span class="line"> <span class="keyword">for</span> y <span class="keyword">in</span> range(height):</span><br><span class="line"> draw.point((x, y), fill=rndColor())</span><br><span class="line"><span class="comment"># 输出文字:</span></span><br><span class="line"><span class="keyword">for</span> t <span class="keyword">in</span> range(<span class="number">4</span>):</span><br><span class="line"> draw.text((<span class="number">60</span> * t + <span class="number">10</span>, <span class="number">10</span>), rndChar(), font=font, fill=rndColor2())</span><br><span class="line"><span class="comment"># 模糊:</span></span><br><span class="line">image = image.filter(ImageFilter.BLUR)</span><br><span class="line">image.save(<span class="string">'code.jpg'</span>, <span class="string">'jpeg'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># virtualenv</span></span><br><span class="line"><span class="comment"># 在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4。</span></span><br><span class="line"><span class="comment"># 所有第三方的包都会被pip安装到Python3的site-packages目录下。</span></span><br><span class="line"><span class="comment"># 首先,我们用pip安装virtualenv:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># $ pip3 install virtualenv</span></span><br><span class="line"><span class="comment"># 然后,假定我们要开发一个新的项目,需要一套独立的Python运行环境,可以这么做:</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"># Mac:~ michael$ mkdir myproject</span></span><br><span class="line"><span class="comment"># Mac:~ michael$ cd myproject/</span></span><br><span class="line"><span class="comment"># Mac:myproject michael$</span></span><br><span class="line"><span class="comment"># 第二步,创建一个独立的Python运行环境,命名为venv:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Mac:myproject michael$ virtualenv --no-site-packages venv</span></span><br><span class="line"><span class="comment"># Using base prefix '/usr/local/.../Python.framework/Versions/3.4'</span></span><br><span class="line"><span class="comment"># New python executable in venv/bin/python3.4</span></span><br><span class="line"><span class="comment"># Also creating executable in venv/bin/python</span></span><br><span class="line"><span class="comment"># Installing setuptools, pip, wheel...done.</span></span><br><span class="line"><span class="comment"># 命令virtualenv就可以创建一个独立的Python运行环境,我们还加上了参数--no-site-packages,这样,已经安装到系统Python环境中的所有第三方包都不会复制过来,这样,我们就得到了一个不带任何第三方包的“干净”的Python运行环境。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 新建的Python环境被放到当前目录下的venv目录。有了venv这个Python环境,可以用source进入该环境:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Mac:myproject michael$ source venv/bin/activate</span></span><br><span class="line"><span class="comment"># (venv)Mac:myproject michael$</span></span><br><span class="line"><span class="comment"># 注意到命令提示符变了,有个(venv)前缀,表示当前环境是一个名为venv的Python环境。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 下面正常安装各种第三方包,并运行python命令:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># (venv)Mac:myproject michael$ pip install jinja2</span></span><br><span class="line"><span class="comment"># ...</span></span><br><span class="line"><span class="comment"># Successfully installed jinja2-2.7.3 markupsafe-0.23</span></span><br><span class="line"><span class="comment"># (venv)Mac:myproject michael$ python myapp.py</span></span><br><span class="line"><span class="comment"># ...</span></span><br><span class="line"><span class="comment"># 在venv环境下,用pip安装的包都被安装到venv这个环境下,系统Python环境不受任何影响。也就是说,venv环境是专门针对myproject这个应用创建的。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 退出当前的venv环境,使用deactivate命令:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># (venv)Mac:myproject michael$ deactivate </span></span><br><span class="line"><span class="comment"># Mac:myproject michael$</span></span><br><span class="line"><span class="comment"># 此时就回到了正常的环境,现在pip或python均是在系统Python环境下执行。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 完全可以针对每个应用创建独立的Python运行环境,这样就可以对每个应用的Python环境进行隔离。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># virtualenv是如何创建“独立”的Python运行环境的呢?原理很简单,就是把系统Python复制一份到virtualenv的环境,用命令source venv/bin/activate进入一个virtualenv环境时,virtualenv会修改相关环境变量,让命令python和pip均指向当前的virtualenv环境。</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"># Python支持多种图形界面的第三方库,包括:</span></span><br><span class="line"><span class="comment"># Tk</span></span><br><span class="line"><span class="comment"># wxWidgets</span></span><br><span class="line"><span class="comment"># Qt</span></span><br><span class="line"><span class="comment"># GTK</span></span><br><span class="line"><span class="comment"># Tkinter</span></span><br><span class="line"><span class="string">r'''</span><br><span class="line">from tkinter import *</span><br><span class="line">import tkinter.messagebox as messagebox</span><br><span class="line"></span><br><span class="line">class Application(Frame):</span><br><span class="line"> def __init__(self, master=None):</span><br><span class="line"> Frame.__init__(self, master)</span><br><span class="line"> self.pack()</span><br><span class="line"> self.createWidgets()</span><br><span class="line"></span><br><span class="line"> def createWidgets(self):</span><br><span class="line"> self.nameInput = Entry(self)</span><br><span class="line"> self.nameInput.pack()</span><br><span class="line"> self.alertButton = Button(self, text='Hello', command=self.hello)</span><br><span class="line"> self.alertButton.pack()</span><br><span class="line"></span><br><span class="line"> def hello(self):</span><br><span class="line"> name = self.nameInput.get() or 'world'</span><br><span class="line"> messagebox.showinfo('Message', 'Hello, %s' % name)</span><br><span class="line"></span><br><span class="line">app = Application()</span><br><span class="line"># 设置窗口标题:</span><br><span class="line">app.master.title('Hello World')</span><br><span class="line"># 主消息循环:</span><br><span class="line">app.mainloop()</span><br><span class="line">'''</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># TCP编程</span></span><br><span class="line"><span class="comment"># 客户端</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 大多数连接都是可靠的TCP连接。创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器。</span></span><br><span class="line"><span class="keyword">import</span> socket,threading,time</span><br><span class="line"></span><br><span class="line">s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)</span><br><span class="line">s.connect((<span class="string">'www.sina.com.cn'</span>, <span class="number">80</span>))</span><br><span class="line"><span class="comment"># AF_INET指定使用IPv4协议,如果要用更先进的IPv6,就指定为AF_INET6。</span></span><br><span class="line"><span class="comment"># SOCK_STREAM指定使用面向流的TCP协议</span></span><br><span class="line">s.send(<span class="string">b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n'</span>)</span><br><span class="line">buffer = []</span><br><span class="line"><span class="keyword">while</span> <span class="keyword">True</span>:</span><br><span class="line"> d = s.recv(<span class="number">1024</span>)</span><br><span class="line"> <span class="keyword">if</span> d:</span><br><span class="line"> buffer.append(d)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line">data = <span class="string">b''</span>.join(buffer)</span><br><span class="line">s.close()</span><br><span class="line">header, html = data.split(<span class="string">b'\r\n\r\n'</span>, <span class="number">1</span>)</span><br><span class="line">print(header.decode(<span class="string">'utf-8'</span>))</span><br><span class="line"><span class="keyword">with</span> open(<span class="string">'sina.html'</span>, <span class="string">'wb'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> f.write(html)</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><br><span class="line"><span class="comment"># 服务器进程</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">tcplink</span><span class="params">(sock, addr)</span>:</span></span><br><span class="line"> print(<span class="string">'accept one new link from %s:%s'</span> % addr)</span><br><span class="line"> sock.send(<span class="string">b'Welcome!'</span>)</span><br><span class="line"> <span class="keyword">while</span> <span class="keyword">True</span>:</span><br><span class="line"> data = sock.recv(<span class="number">1024</span>)</span><br><span class="line"> time.sleep(<span class="number">1</span>)</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> data <span class="keyword">or</span> data.decode(<span class="string">'utf-8'</span>) == <span class="string">'exit'</span>:</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> sock.send((<span class="string">'Hello, %s!'</span> % data.decode(<span class="string">'utf-8'</span>)).encode(<span class="string">'utf-8'</span>))</span><br><span class="line"> sock.close()</span><br><span class="line"> print(<span class="string">'connect from %s:%s closed.'</span> % addr)</span><br><span class="line"><span class="string">r'''</span><br><span class="line">s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)</span><br><span class="line">s.bind(('127.0.0.1', 9999)) #绑定端口号</span><br><span class="line">s.listen(5) #调用listen()方法,指定连接的最大数量</span><br><span class="line">print('waiting for connect ...')</span><br><span class="line">while True:</span><br><span class="line"> sock, addr = s.accept()</span><br><span class="line"> t = threading.Thread(target=tcplink, args=(sock, addr))</span><br><span class="line"> t.start()</span><br><span class="line">'''</span></span><br><span class="line"><span class="comment"># UDP编程</span></span><br><span class="line"><span class="comment"># TCP是建立可靠连接,并且通信双方都可以以流的形式发送数据。相对TCP,UDP则是面向无连接的协议。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就可以直接发数据包。但是,能不能到达就不知道了。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 虽然用UDP传输数据不可靠,但它的优点是和TCP比,速度快,对于不要求可靠到达的数据,就可以使用UDP协议。</span></span><br><span class="line">s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)</span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> [<span class="string">b'Joy'</span>, <span class="string">b'Tom'</span>, <span class="string">b'Mal'</span>]:</span><br><span class="line"> s.sendto(x,(<span class="string">'127.0.0.1'</span>, <span class="number">9999</span>))</span><br><span class="line"> print(s.recv(<span class="number">1024</span>).decode(<span class="string">'utf-8'</span>))</span><br><span class="line">s.close()</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<![CDATA[<h1 id="Python_u5B66_u4E60_282_29"><a href="#Python_u5B66_u4E60_282_29" class="headerlink" title="Python学习(2)"></a>Python学习(2)</h1>]]>
</summary>
<category term="python" scheme="http://www.iwooto.com/tags/python/"/>
</entry>
<entry>
<title><![CDATA[redis下载安装测试]]></title>
<link href="http://www.iwooto.com/2016/04/06/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85%E6%B5%8B%E8%AF%95/"/>
<id>http://www.iwooto.com/2016/04/06/redis下载安装测试/</id>
<published>2016-04-05T16:38:32.000Z</published>
<updated>2016-04-05T17:24:59.372Z</updated>
<content type="html"><![CDATA[<h1 id="redis_u5B89_u88C5"><a href="#redis_u5B89_u88C5" class="headerlink" title="redis安装"></a>redis安装</h1><p>1. 下载地址:<br><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">$ wget http://download.redis.io/releases/redis-<span class="number">3.0</span>.<span class="number">7</span>.tar.gz</span><br></pre></td></tr></table></figure></p>
<p>2. 解压缩<br><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">$ tar xzf redis-<span class="number">3.0</span>.<span class="number">7</span>.tar.gz</span><br></pre></td></tr></table></figure></p>
<p>3. 编译<br><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="built_in">cd</span> redis-<span class="number">3.0</span>.<span class="number">7</span></span><br><span class="line">$ make</span><br><span class="line"><span class="variable">$make</span> install</span><br><span class="line"></span><br><span class="line"><span class="variable">$cp</span> redis.conf /etc/</span><br></pre></td></tr></table></figure></p>
<a id="more"></a>
<p>参数介绍:</p>
<p>make install命令执行完成后,会在/usr/local/bin目录下生成本个可执行文件,分别是redis-server、redis-cli、redis-benchmark、redis-check-aof 、redis-check-dump,它们的作用如下:<br><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">redis-server:Redis服务器的daemon启动程序</span><br><span class="line"></span><br><span class="line">redis-cli:Redis命令行操作工具。也可以用telnet根据其纯文本协议来操作</span><br><span class="line"></span><br><span class="line">redis-benchmark:Redis性能测试工具,测试Redis在当前系统下的读写性能</span><br><span class="line"></span><br><span class="line">redis-check-aof:数据修复</span><br><span class="line"></span><br><span class="line">redis-check-dump:检查导出工具</span><br></pre></td></tr></table></figure></p>
<p>4. 修改系统配置文件,执行命令<br><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">a) <span class="built_in">echo</span> vm.overcommit_memory=<span class="number">1</span> >> /etc/sysctl.conf</span><br><span class="line"></span><br><span class="line">b) sysctl vm.overcommit_memory=<span class="number">1</span> 或执行<span class="built_in">echo</span> vm.overcommit_memory=<span class="number">1</span> >>/proc/sys/vm/overcommit_memory</span><br></pre></td></tr></table></figure></p>
<p>使用数字含义:</p>
<p>0,表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。</p>
<p>1,表示内核允许分配所有的物理内存,而不管当前的内存状态如何。</p>
<p>2,表示内核允许分配超过所有物理内存和交换空间总和的内存</p>
<p>5. 修改redis配置文件<br><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">a) $ <span class="built_in">cd</span> /etc</span><br><span class="line"></span><br><span class="line">b) vi redis.conf</span><br><span class="line"></span><br><span class="line">c) 修改daemonize yes---目的使进程在后台运行</span><br></pre></td></tr></table></figure></p>
<p>参数介绍:</p>
<p>daemonize:是否以后台daemon方式运行</p>
<p>pidfile:pid文件位置</p>
<p>port:监听的端口号</p>
<p>timeout:请求超时时间</p>
<p>loglevel:log信息级别</p>
<p>logfile:log文件位置</p>
<p>databases:开启数据库的数量</p>
<p>save <em> </em>:保存快照的频率,第一个<em>表示多长时间,第三个</em>表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。</p>
<p>rdbcompression:是否使用压缩</p>
<p>dbfilename:数据快照文件名(只是文件名,不包括目录)</p>
<p>dir:数据快照的保存目录(这个是目录)</p>
<p>appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。</p>
<p>appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步)</p>
<p>6. 启动redis<br><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><br><span class="line">```bash</span><br><span class="line">a) $ <span class="built_in">cd</span> /usr/<span class="built_in">local</span>/bin</span><br><span class="line"></span><br><span class="line">b1) ./redis-server</span><br><span class="line">b2) ./redis-server /etc/redis.conf</span><br></pre></td></tr></table></figure></p>
<p>注意:b1这种方式启动redis 使用的是默认配置。也可以通过启动参数告诉redis使用指定配置文件使用下面命令启动。<br>b2启动方式加载redis.conf是一个默认的配置文件。我们可以根据需要使用自己的配置文件。<br>7. 检查是否启动成功<br><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">a) $ ps -ef | grep redis</span><br></pre></td></tr></table></figure></p>
<p>启动redis服务进程后,就可以使用测试客户端程序redis-cli和redis服务交互了。 比如:<br><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">$ ./redis-cli</span><br><span class="line">redis> <span class="built_in">set</span> foo bar</span><br><span class="line">OK</span><br><span class="line">redis> get foo</span><br><span class="line"><span class="string">"bar"</span></span><br></pre></td></tr></table></figure></p>
<h1 id="Ubuntu__u4E0B_u5B89_u88C5redis"><a href="#Ubuntu__u4E0B_u5B89_u88C5redis" class="headerlink" title="Ubuntu 下安装redis"></a>Ubuntu 下安装redis</h1><p>在 Ubuntu 系统安装 Redi 可以使用以下命令:<br><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="variable">$sudo</span> apt-get update</span><br><span class="line"><span class="variable">$sudo</span> apt-get install redis-server</span><br></pre></td></tr></table></figure></p>
<p>启动 Redis<br><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">$redis</span>-server</span><br></pre></td></tr></table></figure></p>
<p>查看 redis 是否启动?<br><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">$redis</span>-cli</span><br></pre></td></tr></table></figure></p>
<p>关闭 Redis<br><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">./redis-cli shutdown</span><br><span class="line">或</span><br><span class="line"><span class="built_in">kill</span> -<span class="number">9</span> PID</span><br></pre></td></tr></table></figure></p>
<p>设置密码访问<br>修改redis.conf文件配置<br><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="comment"># requirepass foobared去掉注释,foobared改为自己的密码,我在这里改为123456</span></span><br></pre></td></tr></table></figure></p>
<h1 id="java_u6D4B_u8BD5_u4EE3_u7801"><a href="#java_u6D4B_u8BD5_u4EE3_u7801" class="headerlink" title="java测试代码"></a>java测试代码</h1><p>导入redis.clients.jedis.Jedis包<br><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"><dependency></span><br><span class="line"> <groupId>redis.clients</groupId></span><br><span class="line"> <artifactId>jedis</artifactId></span><br><span class="line"> <version><span class="number">2.5</span>.<span class="number">2</span></version></span><br><span class="line"></dependency></span><br></pre></td></tr></table></figure></p>
<p>java代码<br><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">package com.iwooto.redis;</span><br><span class="line"></span><br><span class="line">import redis.clients.jedis.Jedis;</span><br><span class="line"></span><br><span class="line">public class TestRedis {</span><br><span class="line"> </span><br><span class="line"> public static void main(String[] args){</span><br><span class="line"></span><br><span class="line"> Jedis jedis = new Jedis(<span class="string">"192.168.233.129"</span>, <span class="number">6379</span>);</span><br><span class="line"> //权限认证</span><br><span class="line"> jedis.auth(<span class="string">"123456"</span>);</span><br><span class="line"> //查看服务是否运行</span><br><span class="line"> System.out.println(<span class="string">"Server is running: "</span>+jedis.ping());</span><br><span class="line"> jedis.set(<span class="string">"test"</span>, <span class="string">"testValue"</span>);</span><br><span class="line"> String str = jedis.get(<span class="string">"test"</span>);</span><br><span class="line"> System.out.println(str);</span><br><span class="line"> jedis.close();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<h1 id="redis_u9519_u8BEF_u8BB0_u5F55"><a href="#redis_u9519_u8BEF_u8BB0_u5F55" class="headerlink" title="redis错误记录"></a>redis错误记录</h1><p>Q:MISCONF Redis is configured to save RDB snapshots<br>A:<br><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">启动客户端./redis-cli </span><br><span class="line">输入 config <span class="built_in">set</span> stop-writes-on-bgsave-error no</span><br></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<![CDATA[<h1 id="redis_u5B89_u88C5"><a href="#redis_u5B89_u88C5" class="headerlink" title="redis安装"></a>redis安装</h1><p>1. 下载地址:<br><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">$ wget http://download.redis.io/releases/redis-<span class="number">3.0</span>.<span class="number">7</span>.tar.gz</span><br></pre></td></tr></table></figure></p>
<p>2. 解压缩<br><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">$ tar xzf redis-<span class="number">3.0</span>.<span class="number">7</span>.tar.gz</span><br></pre></td></tr></table></figure></p>
<p>3. 编译<br><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="built_in">cd</span> redis-<span class="number">3.0</span>.<span class="number">7</span></span><br><span class="line">$ make</span><br><span class="line"><span class="variable">$make</span> install</span><br><span class="line"></span><br><span class="line"><span class="variable">$cp</span> redis.conf /etc/</span><br></pre></td></tr></table></figure></p>]]>
</summary>
<category term="redis" scheme="http://www.iwooto.com/tags/redis/"/>
</entry>
<entry>
<title><![CDATA[linux上传下载文件]]></title>
<link href="http://www.iwooto.com/2016/04/05/linux%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E6%96%87%E4%BB%B6/"/>
<id>http://www.iwooto.com/2016/04/05/linux上传下载文件/</id>
<published>2016-04-05T14:08:47.000Z</published>
<updated>2016-04-05T16:40:12.939Z</updated>
<content type="html"><![CDATA[<h1 id="u5B89_u88C5lrzsz"><a href="#u5B89_u88C5lrzsz" class="headerlink" title="安装lrzsz"></a>安装lrzsz</h1><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">sudo apt-get install lrzsz</span><br><span class="line">或</span><br><span class="line">sudo yum install lrzsz</span><br><span class="line"></span><br><span class="line">rz上传文件</span><br><span class="line">rz</span><br><span class="line">sz下载文件</span><br><span class="line">sz filename</span><br></pre></td></tr></table></figure>
<a id="more"></a>
<h1 id="u6587_u4EF6_u590D_u5236cp"><a href="#u6587_u4EF6_u590D_u5236cp" class="headerlink" title="文件复制cp"></a>文件复制cp</h1><p>语法: cp [选项] 源文件或目录 目标文件或目录<br> 该命令的各选项含义如下: </p>
<ul>
<li>a 该选项通常在拷贝目录时使用。它保留链接、文件属性,并递归地拷贝目录,其作用等于dpR选项的组合。 </li>
<li>d 拷贝时保留链接。 </li>
<li>f 删除已经存在的目标文件而不提示。 </li>
<li>i 和f选项相反,在覆盖目标文件之前将给出提示要求用户确认。回答y时目标文件将被覆盖,是交互式拷贝。 </li>
<li>p 此时cp除复制源文件的内容外,还将把其修改时间和访问权限也复制到新文件中。 </li>
<li>r 若给出的源文件是一目录文件,此时cp将递归复制该目录下所有的子目录和文件。此时目标文件必须为一个目录名。 </li>
<li>l 不作拷贝,只是链接文件。<br> 需要说明的是,为防止用户在不经意的情况下用cp命令破坏另一个文件,如用户指定的目标文件名已存在,用cp命令拷贝文件后,这个文件就会被新源文件覆盖,因此,建议用户在使用cp命令拷贝文件时,最好使用i选项。</li>
</ul>
<h1 id="u6587_u4EF6_u5220_u9664rm"><a href="#u6587_u4EF6_u5220_u9664rm" class="headerlink" title="文件删除rm"></a>文件删除rm</h1><p>语法: rm [选项] 文件名</p>
<ul>
<li>f 忽略不存在的文件,从不给出提示。 </li>
<li>r 指示rm将参数中列出的全部目录和子目录均递归地删除。 </li>
<li>i 进行交互式删除。</li>
</ul>
<p> 使用rm命令要小心。因为一旦文件被删除,它是不能被恢复的。了防止这种情况的发生,可以使用i选项来逐个确认要删除的文件。如果用户输入y,文件将被删除。如果输入任何其他东西,文件则不会删除。</p>
<h1 id="u6587_u4EF6_u79FB_u52A8mv"><a href="#u6587_u4EF6_u79FB_u52A8mv" class="headerlink" title="文件移动mv"></a>文件移动mv</h1><p> 语法: mv [选项] 源文件或目录 目标文件或目录</p>
<p> 说 明:视mv命令中第二个参数类型的不同(是目标文件还是目标目录),mv命令将文件重命名或将其移至一个新的目录中。当第二个参数类型是文件时,mv命令 完成文件重命名,此时,源文件只能有一个(也可以是源目录名),它将所给的源文件或目录重命名为给定的目标文件名。当第二个参数是已存在的目录名称时,源 文件或目录参数可以有多个,mv命令将各参数指定的源文件均移至目标目录中。在跨文件系统移动文件时,mv先拷贝,再将原有文件删除,而链至该文件的链接 也将丢失。 </p>
<p> 命令中各选项的含义为: </p>
<ul>
<li>I 交互方式操作。如果mv操作将导致对已存在的目标文件的覆盖,此时系统询问是否重写,要求用户回答y或n,这样可以避免误覆盖文件。 </li>
<li>f 禁止交互操作。在mv操作要覆盖某已有的目标文件时不给任何指示,指定此选项后,i选项将不再起作用。</li>
</ul>
<p> 如果所给目标文件(不是目录)已存在,此时该文件的内容将被新文件覆盖。为防止用户用mv命令破坏另一个文件,使用mv命令移动文件时,最好使用i选项。</p>
]]></content>
<summary type="html">
<![CDATA[<h1 id="u5B89_u88C5lrzsz"><a href="#u5B89_u88C5lrzsz" class="headerlink" title="安装lrzsz"></a>安装lrzsz</h1><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">sudo apt-get install lrzsz</span><br><span class="line">或</span><br><span class="line">sudo yum install lrzsz</span><br><span class="line"></span><br><span class="line">rz上传文件</span><br><span class="line">rz</span><br><span class="line">sz下载文件</span><br><span class="line">sz filename</span><br></pre></td></tr></table></figure>]]>
</summary>
<category term="Linux" scheme="http://www.iwooto.com/tags/Linux/"/>
</entry>
<entry>
<title><![CDATA[js模板引擎]]></title>
<link href="http://www.iwooto.com/2016/03/30/js%E6%A8%A1%E6%9D%BF%E5%BC%95%E6%93%8E/"/>
<id>http://www.iwooto.com/2016/03/30/js模板引擎/</id>
<published>2016-03-29T17:21:33.000Z</published>
<updated>2016-03-29T17:21:57.703Z</updated>
<content type="html"></content>
<summary type="html">
</summary>
<category term="tags" scheme="http://www.iwooto.com/tags/tags/"/>
</entry>
<entry>
<title><![CDATA[websocket]]></title>
<link href="http://www.iwooto.com/2016/03/21/websocket/"/>
<id>http://www.iwooto.com/2016/03/21/websocket/</id>
<published>2016-03-21T15:20:55.000Z</published>
<updated>2016-04-05T16:43:25.689Z</updated>
<content type="html"><![CDATA[<h1 id="u4E00_u3001tomcat_u4E2Dwebsocket-jar_u7F16_u5199_u7684websocket"><a href="#u4E00_u3001tomcat_u4E2Dwebsocket-jar_u7F16_u5199_u7684websocket" class="headerlink" title="一、tomcat中websocket.jar编写的websocket"></a>一、tomcat中websocket.jar编写的websocket</h1><h1 id="u4E8C_u3001springMVC4-0_u4EE5_u540E_u7248_u672C_u81EA_u5E26_u7684websocket"><a href="#u4E8C_u3001springMVC4-0_u4EE5_u540E_u7248_u672C_u81EA_u5E26_u7684websocket" class="headerlink" title="二、springMVC4.0以后版本自带的websocket"></a>二、springMVC4.0以后版本自带的websocket</h1>]]></content>
<summary type="html">
<![CDATA[<h1 id="u4E00_u3001tomcat_u4E2Dwebsocket-jar_u7F16_u5199_u7684websocket"><a href="#u4E00_u3001tomcat_u4E2Dwebsocket-jar_u7F16_u5199_u7684web]]>
</summary>
<category term="websocket" scheme="http://www.iwooto.com/tags/websocket/"/>
</entry>
<entry>
<title><![CDATA[gradle使用]]></title>
<link href="http://www.iwooto.com/2016/03/09/gradle%E4%BD%BF%E7%94%A8/"/>
<id>http://www.iwooto.com/2016/03/09/gradle使用/</id>
<published>2016-03-09T15:44:23.000Z</published>
<updated>2016-03-09T16:00:38.788Z</updated>
<content type="html"><![CDATA[<h1 id="gradle"><a href="#gradle" class="headerlink" title="gradle"></a>gradle</h1><p>听说gradle这个工具各种厉害就自己安装了一下,把玩把玩<a id="more"></a></p>
<h1 id="gradle_u5B89_u88C5"><a href="#gradle_u5B89_u88C5" class="headerlink" title="gradle安装"></a>gradle安装</h1><p>源码下载使用迅雷下载<br><a href="https://downloads.gradle.org/distributions/gradle-2.11-all.zip" target="_blank" rel="external">https://downloads.gradle.org/distributions/gradle-2.11-all.zip</a><br>配置环境变量<br><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">GRADLE_HOEM: D:\gradle-<span class="number">2.11</span></span><br><span class="line">Path: %GRADLE_HOME%\bin;</span><br></pre></td></tr></table></figure></p>
<p>查看安装是否成功<br>cmd下: gradle -v #显示版本信息</p>
<h1 id="eclipse_u5B89_u88C5gradle"><a href="#eclipse_u5B89_u88C5gradle" class="headerlink" title="eclipse安装gradle"></a>eclipse安装gradle</h1><p>Help->install new software->add<br><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">name: gradle</span><br><span class="line">location:http://dist.springsource.com/release/TOOLS/gradle</span><br></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<![CDATA[<h1 id="gradle"><a href="#gradle" class="headerlink" title="gradle"></a>gradle</h1><p>听说gradle这个工具各种厉害就自己安装了一下,把玩把玩]]>
</summary>
<category term="gradle" scheme="http://www.iwooto.com/tags/gradle/"/>
</entry>
<entry>
<title><![CDATA[keytool的使用]]></title>
<link href="http://www.iwooto.com/2016/03/09/keytool%E7%9A%84%E4%BD%BF%E7%94%A8/"/>
<id>http://www.iwooto.com/2016/03/09/keytool的使用/</id>
<published>2016-03-09T14:59:35.000Z</published>
<updated>2016-03-09T15:33:44.241Z</updated>
<content type="html"><![CDATA[<h1 id="u6982_u5FF5"><a href="#u6982_u5FF5" class="headerlink" title="概念"></a>概念</h1><p>keytool 是个密钥和证书管理工具。它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务。<br>在JDK1.4以后的版本中都包含了这一工具,它的位置为%JAVA_HOME%\bin\keytool.exe<a id="more"></a></p>
<h1 id="u4F7F_u7528_u6559_u7A0B_28java_u73AF_u5883_u53D8_u91CF_u5DF2_u7ECF_u914D_u597D_u7684_u60C5_u51B5_u4E0B_u8FDB_u884C_u7684_29"><a href="#u4F7F_u7528_u6559_u7A0B_28java_u73AF_u5883_u53D8_u91CF_u5DF2_u7ECF_u914D_u597D_u7684_u60C5_u51B5_u4E0B_u8FDB_u884C_u7684_29" class="headerlink" title="使用教程(java环境变量已经配好的情况下进行的)"></a>使用教程(java环境变量已经配好的情况下进行的)</h1><p>1.查看帮助 cmd 命令行中输入keytool<br>2.创建证书<br><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">keytool -genkeypair -alias <span class="string">"iwooto.com"</span> -keystore <span class="string">"iwooto.keystore"</span></span><br></pre></td></tr></table></figure></p>
<p>3.查看秘钥库里面的证书<br><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">keytool -list -keystore iwooto.keystore</span><br></pre></td></tr></table></figure></p>
<p>4.导出证书到文件<br><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">keytool -export -alias iwooto.com -file iwooto.crt -keystore iwooto.keystore</span><br></pre></td></tr></table></figure></p>
<p>5.导入证书<br><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">#导入iwooto.crt证书到test秘钥库</span></span><br><span class="line">keytool -import -keystore <span class="built_in">test</span> -file iwooto.crt</span><br><span class="line"><span class="comment">#导入iwooto.crt证书到JDK秘钥库(如果报错先删除jdk下的cacerts文件)</span></span><br><span class="line">keytool -import -keystore D:\Java\jdk1.<span class="number">7.0</span>_71\jre\lib\security\cacerts -file iwooto.crt</span><br><span class="line"><span class="comment">#或</span></span><br><span class="line">keytool -import -keystore D:\Java\jdk1.<span class="number">7.0</span>_71\jre\lib\security\cacerts -file iwooto.crt -alias iwooto.com</span><br></pre></td></tr></table></figure></p>
<p>6.查看证书信息<br><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">keytool -printcert -file iwooto.crt</span><br></pre></td></tr></table></figure></p>
<p>7.修改证书条目口令<br><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">keytool -keypasswd -alias iwooto.com -keystore iwooto.keystore</span><br></pre></td></tr></table></figure></p>
<p>8.删除秘钥库的条目<br><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">keytool -delete -keystore iwooto.keystore -alias iwooto.com</span><br></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<![CDATA[<h1 id="u6982_u5FF5"><a href="#u6982_u5FF5" class="headerlink" title="概念"></a>概念</h1><p>keytool 是个密钥和证书管理工具。它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务。<br>在JDK1.4以后的版本中都包含了这一工具,它的位置为%JAVA_HOME%\bin\keytool.exe]]>
</summary>
<category term="java" scheme="http://www.iwooto.com/tags/java/"/>
</entry>
<entry>
<title><![CDATA[linux文件目录权限]]></title>
<link href="http://www.iwooto.com/2016/02/25/linux%E6%96%87%E4%BB%B6%E7%9B%AE%E5%BD%95%E6%9D%83%E9%99%90/"/>
<id>http://www.iwooto.com/2016/02/25/linux文件目录权限/</id>
<published>2016-02-25T15:46:13.000Z</published>
<updated>2016-04-06T15:57:59.333Z</updated>
<content type="html"><![CDATA[<h2 id="u4F7F_u7528vim_u4FEE_u6539_u6587_u4EF6_u62A5_u9519"><a href="#u4F7F_u7528vim_u4FEE_u6539_u6587_u4EF6_u62A5_u9519" class="headerlink" title="使用vim修改文件报错"></a>使用vim修改文件报错</h2><p>系统提示如下:W10:warning:changing a readonly file,E37: No write since last change (add ! to override)<br>表明这是一个只读的文件需要修改文件的权限.<a id="more"></a></p>
<h2 id="u6587_u4EF6/_u76EE_u5F55_u6743_u9650_u8BBE_u7F6E_u547D_u4EE4_uFF1Achmod"><a href="#u6587_u4EF6/_u76EE_u5F55_u6743_u9650_u8BBE_u7F6E_u547D_u4EE4_uFF1Achmod" class="headerlink" title="文件/目录权限设置命令:chmod"></a>文件/目录权限设置命令:chmod</h2><p>这是Linux系统管理员最常用到的命令之一,它用于改变文件或目录的访问权限。该命令有两种用法: </p>
<p>用包含字母和操作符表达式的文字设定法 </p>
<p>其语法格式为:chmod [who] [opt] [mode] 文件/目录名 </p>
<p>其中who表示对象,是以下字母中的一个或组合: </p>
<p>u:表示文件所有者<br>g:表示同组用户<br>o:表示其它用户<br>a:表示所有用户<br>opt则是代表操作,可以为:<br>+:添加某个权限<br>-:取消某个权限<br>=:赋予给定的权限,并取消原有的权限<br>而mode则代表权限:<br>r:可读<br>w:可写<br>x:可执行 </p>
<p>例如:为同组用户增加对文件a.txt的读写权限: </p>
<p>chmod g+rw a.txt </p>
<p>用数字设定法 </p>
<p>而数字设定法则更为简单:chmod [mode] 文件名 </p>
<p>关键是mode的取值,一开始许多初学者会被搞糊涂,其实很简单,我们将rwx看成二进制数,如果有则有1表示,没有则有0表示,那么rwx r-x r- -则可以表示成为: </p>
<p>111 101 100 </p>
<p>再将其每三位转换成为一个十进制数,就是754。 </p>
<p>例如,我们想让a.txt这个文件的权限为: </p>
<p>自己 同组用户 其他用户<br>可读 是 是 是<br>可写 是 是 可执行 </p>
<p>那么,我们先根据上表得到权限串为:rw-rw-r–,那么转换成二进制数就是110 110 100,再每三位转换成为一个十进制数,就得到664,因此我 们执行命令: </p>
<p>chmod 664 a.txt</p>
<h2 id="vi__u64CD_u4F5C_28_u8F6C_29"><a href="#vi__u64CD_u4F5C_28_u8F6C_29" class="headerlink" title="vi 操作(转)"></a>vi 操作(转)</h2><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">Ctrl+u:向文件首翻半屏; </span><br><span class="line">Ctrl+d:向文件尾翻半屏;</span><br><span class="line">Ctrl+f:向文件尾翻一屏; </span><br><span class="line">Ctrl+b:向文件首翻一屏; </span><br><span class="line">Esc:从编辑模式切换到命令模式; </span><br><span class="line">ZZ:命令模式下保存当前文件所做的修改后退出vi; </span><br><span class="line">:行号:光标跳转到指定行的行首; </span><br><span class="line">:$:光标跳转到最后一行的行首; </span><br><span class="line">x或X:删除一个字符,x删除光标后的,而X删除光标前的; </span><br><span class="line">D:删除从当前光标到光标所在行尾的全部字符; </span><br><span class="line">dd:删除光标行正行内容; </span><br><span class="line">ndd:删除当前行及其后n-<span class="number">1</span>行; </span><br><span class="line">nyy:将当前行及其下n行的内容保存到寄存器?中,其中?为一个字母,n为一个数字;</span><br><span class="line">p:粘贴文本操作,用于将缓存区的内容粘贴到当前光标所在位置的下方;</span><br><span class="line">P:粘贴文本操作,用于将缓存区的内容粘贴到当前光标所在位置的上方;</span><br><span class="line">/字符串:文本查找操作,用于从当前光标所在位置开始向文件尾部查找指定字符串的内容,查找的字符串会被加亮显示;</span><br><span class="line">?字符串:文本查找操作,用于从当前光标所在位置开始向文件头部查找指定字符串的内容,查找的字符串会被加亮显示;</span><br><span class="line">a,bs/F/T:替换文本操作,用于在第a行到第b行之间,将F字符串换成T字符串。其中,“s/”表示进行替换操作;</span><br><span class="line">a:在当前字符后添加文本;</span><br><span class="line">A:在行末添加文本;</span><br><span class="line">i:在当前字符前插入文本;</span><br><span class="line">I:在行首插入文本;</span><br><span class="line">o:在当前行后面插入一空行;</span><br><span class="line">O:在当前行前面插入一空行;</span><br><span class="line">:wq:在命令模式下,执行存盘退出操作;</span><br><span class="line">:w:在命令模式下,执行存盘操作;</span><br><span class="line">:w!:在命令模式下,执行强制存盘操作;</span><br><span class="line">:q:在命令模式下,执行退出vi操作;</span><br><span class="line">:q!:在命令模式下,执行强制退出vi操作;</span><br><span class="line">:e文件名:在命令模式下,打开并编辑指定名称的文件;</span><br><span class="line">:n:在命令模式下,如果同时打开多个文件,则继续编辑下一个文件;</span><br><span class="line">:f:在命令模式下,用于显示当前的文件名、光标所在行的行号以及显示比例;</span><br><span class="line">:<span class="built_in">set</span> number:在命令模式下,用于在最左端显示行号;</span><br><span class="line">:<span class="built_in">set</span> nonumber:在命令模式下,用于在最左端不显示行号;</span><br><span class="line"><span class="comment"># 选项</span></span><br><span class="line">+<行号>:从指定行号的行开始先是文本内容;</span><br><span class="line">-b:以二进制模式打开文件,用于编辑二进制文件和可执行文件;</span><br><span class="line">-c<指令>:在完成对第一个文件编辑任务后,执行给出的指令;</span><br><span class="line"><span class="operator">-d</span>:以diff模式打开文件,当多个文件编辑时,显示文件差异部分;</span><br><span class="line"><span class="operator">-l</span>:使用lisp模式,打开“lisp”和“showmatch”;</span><br><span class="line">-m:取消写文件功能,重设“write”选项;</span><br><span class="line">-M:关闭修改功能;</span><br><span class="line">-n:不实用缓存功能;</span><br><span class="line">-o<文件数目>:指定同时打开指定数目的文件;</span><br><span class="line">-R:以只读方式打开文件;</span><br><span class="line"><span class="operator">-s</span>:安静模式,不现实指令的任何错误信息。</span><br></pre></td></tr></table></figure>
<h1 id="u77E5_u8BC6_u6269_u5C55"><a href="#u77E5_u8BC6_u6269_u5C55" class="headerlink" title="知识扩展"></a>知识扩展</h1><p>vi编辑器有三种工作方式:命令方式、输入方式和ex转义方式。通过相应的命令或操作,在这三种工作方式之间可以进行转换。 </p>
<h1 id="u547D_u4EE4_u65B9_u5F0F"><a href="#u547D_u4EE4_u65B9_u5F0F" class="headerlink" title="命令方式"></a>命令方式</h1><p>在Shell提示符后输入命令vi,进入vi编辑器,并处于vi的命令方式。此时,从键盘上输入的任何字符都被作为编辑命令来解释,例如,a(append)表示附加命令,i(insert)表示插入命令,x表示删除字符命令等。如果输入的字符不是vi的合法命令,则机器发出“报警声”,光标不移动。另外,在命令方式下输入的字符(即vi命令)并不在屏幕上显示出来,例如,输入i,屏幕上并无变化,但通过执行i命令,编辑器的工作方式却发生变化:由命令方式变为输入方式。 </p>
<h1 id="u8F93_u5165_u65B9_u5F0F"><a href="#u8F93_u5165_u65B9_u5F0F" class="headerlink" title="输入方式"></a>输入方式</h1><p>通过输入vi的插入命令(i)、附加命令(a)、打开命令(o)、替换命令(s)、修改命令(c)或取代命令(r)可以从命令方式进入输入方式。在输入方式下,从键盘上输入的所有字符都被插入到正在编辑的缓冲区中,被当做该文件的正文。进入输入方式后,输入的可见字符都在屏幕上显示出来,而编辑命令不再起作用,仅作为普通字母出现。例如,在命令方式下输入字母i,进到输入方式,然后再输入i,就在屏幕上相应光标处添加一个字母i。 由输入方式回到命令方式的办法是按下Esc键。如果已在命令方式下,那么按下Esc键就会发出“嘟嘟”声。为了确保用户想执行的vi命令是在命令方式下输入的,不妨多按几下Esc键,听到嘟声后再输入命令。</p>
<h1 id="ex_u8F6C_u4E49_u65B9_u5F0F"><a href="#ex_u8F6C_u4E49_u65B9_u5F0F" class="headerlink" title="ex转义方式"></a>ex转义方式</h1><p>vi和ex编辑器的功能是相同的,二者的主要区别是用户界面。在vi中,命令通常是单个字母,如a,x,r等。而在ex中,命令是以Enter;键结束的命令行。vi有一个专门的“转义”命令,可访问很多面向行的ex命令。为使用ex转义方式,可输入一个冒号(:)。作为ex命令提示符,冒号出现在状态行(通常在屏幕最下一行)。按下中断键(通常是Del键),可终止正在执行的命令。多数文件管理命令都是在ex转义方式下执行的(例如,读取文件,把编辑缓冲区的内容写到文件中等)。转义命令执行后,自动回到命令方式。例如: :1,$s/I/i/g 按Enter键</p>
<p><a href="http://man.linuxde.net/vi" target="_blank" rel="external">来自: http://man.linuxde.net/vi</a></p>
]]></content>
<summary type="html">
<![CDATA[<h2 id="u4F7F_u7528vim_u4FEE_u6539_u6587_u4EF6_u62A5_u9519"><a href="#u4F7F_u7528vim_u4FEE_u6539_u6587_u4EF6_u62A5_u9519" class="headerlink" title="使用vim修改文件报错"></a>使用vim修改文件报错</h2><p>系统提示如下:W10:warning:changing a readonly file,E37: No write since last change (add ! to override)<br>表明这是一个只读的文件需要修改文件的权限.]]>
</summary>
<category term="Linux" scheme="http://www.iwooto.com/tags/Linux/"/>
</entry>
<entry>
<title><![CDATA[表值函数和标量函数]]></title>
<link href="http://www.iwooto.com/2016/02/04/%E8%A1%A8%E5%80%BC%E5%87%BD%E6%95%B0%E5%92%8C%E6%A0%87%E9%87%8F%E5%87%BD%E6%95%B0/"/>
<id>http://www.iwooto.com/2016/02/04/表值函数和标量函数/</id>
<published>2016-02-04T12:36:16.000Z</published>
<updated>2016-02-04T15:25:22.454Z</updated>
<content type="html"><![CDATA[<h1 id="u57FA_u672C_u89E3_u91CA"><a href="#u57FA_u672C_u89E3_u91CA" class="headerlink" title="基本解释"></a>基本解释</h1><p>表值函数:返回类型为table类型,table类型相当于一张存储在内存中的虚拟的一张虚拟表</p>
<p>标量值函数:返回类型只能是基类型,其返回值类型为除TEXT、NTEXT 、IMAGE、CURSOR、 TIMESTAMP 和TABLE 类型外的其它数据类型。函数体语句定义在BEGIN-END语句内,其中包含了可以返回值的Transact-SQL 命令。调用返回表的 SQL Server 内置函数时,必须将前缀 :: 添加至函数名:<br>SELECT * FROM ::fn_helpcollations()</p>
<p>存储过程:可包含程序流、逻辑以及对数据库的查询。它们可以接受参数、输出参数、返回单个或多个结果集以及返回值。</p>
<p>函数与存储过程本质上没区别。只是函数有如:只能返回一个变量的限制。而存储过程可以返回多个。而函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程不行。执行的本质都一样。函数限制比较多,比如不能用临时表,只能用表变量.还有一些函数都不可用等等.而存储过程的限制相对就比较少<br><a href="http://knowsky.com/534162.html" target="_blank" rel="external">转载地址</a></p>
]]></content>
<summary type="html">
<![CDATA[<h1 id="u57FA_u672C_u89E3_u91CA"><a href="#u57FA_u672C_u89E3_u91CA" class="headerlink" title="基本解释"></a>基本解释</h1><p>表值函数:返回类型为table类型,table类]]>
</summary>
<category term="sql" scheme="http://www.iwooto.com/tags/sql/"/>
</entry>
<entry>
<title><![CDATA[css强制换行与不换行]]></title>
<link href="http://www.iwooto.com/2016/02/01/css%E5%BC%BA%E5%88%B6%E6%8D%A2%E8%A1%8C%E4%B8%8E%E4%B8%8D%E6%8D%A2%E8%A1%8C/"/>
<id>http://www.iwooto.com/2016/02/01/css强制换行与不换行/</id>
<published>2016-02-01T13:00:32.000Z</published>
<updated>2016-02-01T13:35:13.120Z</updated>
<content type="html"><![CDATA[<h2 id="u57FA_u672C_u89E3_u91CA"><a href="#u57FA_u672C_u89E3_u91CA" class="headerlink" title="基本解释"></a>基本解释</h2><p>word-break:break-all;只对英文起作用,以字母作为换行依据<br>word-wrap:break-word; 只对英文起作用,以单词作为换行依据<br>white-space:pre-wrap; 只对中文起作用,强制换行<br>white-space:nowrap; 强制不换行,都起作用<br>white-space:nowrap; overflow:hidden; text-overflow:ellipsis;不换行,超出部分隐藏且以省略号形式出现<br>注意,一定要指定容器的宽度,不然的话是没有用的。<a id="more"></a><br>注意word-break 是IE5+专有属性<br>语法:<br>word-break : normal | break-all | keep-all<br>对于中文,应该使用break-all 。<br>强制不换行<br><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">div{white-space:nowrap;}</span><br></pre></td></tr></table></figure></p>
<p>自动换行<br><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">div{word-wrap: <span class="built_in">break</span>-word;word-break: normal;}</span><br></pre></td></tr></table></figure></p>
<p>强制英文单词断行<br><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">div{word-break:<span class="built_in">break</span>-all;}</span><br></pre></td></tr></table></figure></p>
<h2 id="CSS_u8BBE_u7F6E_u4E0D_u8F6C_u884C_3A"><a href="#CSS_u8BBE_u7F6E_u4E0D_u8F6C_u884C_3A" class="headerlink" title="CSS设置不转行:"></a>CSS设置不转行:</h2><p>overflow:hidden 隐藏<br>white-space:normal 默认<br>pre 换行和其他空白字符都将受到保护<br>nowrap 强制在同一行内显示所有文本,直到文本结束或者遭遇 br 对象</p>
<h2 id="u8BBE_u7F6E_u5F3A_u884C_u6362_u884C"><a href="#u8BBE_u7F6E_u5F3A_u884C_u6362_u884C" class="headerlink" title="设置强行换行"></a>设置强行换行</h2><p>word-break:<br>normal : 依照亚洲语言和非亚洲语言的文本规则,允许在字内换行<br>break-all: 该行为与亚洲语言的normal相同。也允许非亚洲语言文本行的任意字内断开。该值适合包含一些非亚洲文本的亚洲文本<br>keep-all : 与所有非亚洲语言的normal相同。对于中文,韩文,日文,不允许字断开。</p>
<h2 id="u82F1_u6587_u4E0D_u6362_u884C"><a href="#u82F1_u6587_u4E0D_u6362_u884C" class="headerlink" title="英文不换行"></a>英文不换行</h2><p>CSS里加上 word-break: break-all; 问题解决。这个问题只有IE才有,在FF下测试,FF可以自己加滚动条,这样也不影响效果<br>建议大家做Skin时,记得在body里加 word-break: break-all; 这样可以解决IE的框架被英文撑开的问题<br>以下引用word-break的说明, 注意word-break 是IE5+专有属性<br>语法:<br>word-break : normal | break-all | keep-all<br>参数:<br>normal : 依照亚洲语言和非亚洲语言的文本规则,允许在字内换行<br>break-all: 该行为与亚洲语言的normal相同。也允许非亚洲语言文本行的任意字内断开。该值适合包含一些非亚洲文本的亚洲文本<br>keep-all : 与所有非亚洲语言的normal相同。对于中文,韩文,日文,不允许字断开。适合包含少量亚洲文本的非亚洲文本<br>说明:<br>设置或检索对象内文本的字内换行行为。尤其在出现多种语言时。<br>对于中文,应该使用break-all 。<br>div {word-break : break-all; }</p>
<h2 id="u9AD8_u7EA7_u5E94_u7528__u8BA9_u6587_u5B57_u81EA_u9002_u5E94table_u5BBD_u5EA6"><a href="#u9AD8_u7EA7_u5E94_u7528__u8BA9_u6587_u5B57_u81EA_u9002_u5E94table_u5BBD_u5EA6" class="headerlink" title="高级应用 让文字自适应table宽度"></a>高级应用 让文字自适应table宽度</h2><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">table {table-layout:fixed}</span><br><span class="line">table > th{white-space: nowrap;}</span><br><span class="line">table >tbody> td{text-overflow:ellipsis;overflow:hidden;white-space: nowrap;padding:<span class="number">2</span>px}</span><br></pre></td></tr></table></figure>
<h1 id="u5173_u952E_u6837_u5F0F_3A"><a href="#u5173_u952E_u6837_u5F0F_3A" class="headerlink" title="关键样式:"></a>关键样式:</h1><p>table-layout:fixed 固定布局的算法,则表格被呈递的默认宽度为 100% (For IE,Mozilla)</p>
<p>text-overflow:ellipsis 当对象内文本溢出时显示省略标记(…) (For IE)</p>
<p>overflow:hidden 不显示超过对象尺寸的内容 (For IE,Mozilla) </p>
<p>white-space: nowrap 强制在同一行内显示所有文本,直到文本结束或者遭遇 br 对象 (For IE,Mozilla)</p>
<p>转载<a href="/'http://blog.csdn.net/ldl22847/article/details/7247702'">CSS强制英文、中文换行与不换行</a><br>转载<a href="/'http://www.feitec.com/showart.asp?id=825'">Css让文字自适应Table宽度</a></p>
]]></content>
<summary type="html">
<![CDATA[<h2 id="u57FA_u672C_u89E3_u91CA"><a href="#u57FA_u672C_u89E3_u91CA" class="headerlink" title="基本解释"></a>基本解释</h2><p>word-break:break-all;只对英文起作用,以字母作为换行依据<br>word-wrap:break-word; 只对英文起作用,以单词作为换行依据<br>white-space:pre-wrap; 只对中文起作用,强制换行<br>white-space:nowrap; 强制不换行,都起作用<br>white-space:nowrap; overflow:hidden; text-overflow:ellipsis;不换行,超出部分隐藏且以省略号形式出现<br>注意,一定要指定容器的宽度,不然的话是没有用的。]]>
</summary>
<category term="css" scheme="http://www.iwooto.com/tags/css/"/>
</entry>
<entry>
<title><![CDATA[有时候有时候]]></title>
<link href="http://www.iwooto.com/2016/01/30/%E6%9C%89%E6%97%B6%E5%80%99%E6%9C%89%E6%97%B6%E5%80%99/"/>
<id>http://www.iwooto.com/2016/01/30/有时候有时候/</id>
<published>2016-01-30T09:55:46.000Z</published>
<updated>2016-01-30T09:57:24.399Z</updated>
<content type="html"><![CDATA[<p>有时候事情其实并不是你想象中的那么难</p>
]]></content>
<summary type="html">
<![CDATA[<p>有时候事情其实并不是你想象中的那么难</p>
]]>
</summary>
<category term="essays" scheme="http://www.iwooto.com/tags/essays/"/>
</entry>
<entry>
<title><![CDATA[java 代码中添加log日志]]></title>
<link href="http://www.iwooto.com/2016/01/30/java-%E4%BB%A3%E7%A0%81%E4%B8%AD%E6%B7%BB%E5%8A%A0log%E6%97%A5%E5%BF%97/"/>
<id>http://www.iwooto.com/2016/01/30/java-代码中添加log日志/</id>
<published>2016-01-30T08:41:36.000Z</published>
<updated>2016-01-30T09:00:10.815Z</updated>
<content type="html"><![CDATA[<h1 id="1-_u5F97_u5230_u8BB0_u5F55_u5668"><a href="#1-_u5F97_u5230_u8BB0_u5F55_u5668" class="headerlink" title="1.得到记录器"></a>1.得到记录器</h1><p>使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:<br><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">public static Logger getLogger( String name),</span><br></pre></td></tr></table></figure></p>
<p>通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。<a id="more"></a><br>Name一般取本类的名字,比如:<br><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">static Logger logger = Logger.getLogger ( BaseController.class.getName () ) ;</span><br></pre></td></tr></table></figure></p>
<p>通过类本身获得记录器:<br><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">private Logger logger = Logger.getLogger ( this.class ) ;</span><br></pre></td></tr></table></figure></p>
<h1 id="2-_u8BFB_u53D6_u914D_u7F6E_u6587_u4EF6"><a href="#2-_u8BFB_u53D6_u914D_u7F6E_u6587_u4EF6" class="headerlink" title="2.读取配置文件"></a>2.读取配置文件</h1><p>当获得了日志记录器之后,第二步将配置Log4j环境,其语法为:<br><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="number">1</span>.自动快速地使用缺省Log4j环境。 </span><br><span class="line">BasicConfigurator.configure (); </span><br><span class="line"></span><br><span class="line">//<span class="number">2</span>.读取使用Java的特性文件编写的配置文件。</span><br><span class="line">PropertyConfigurator.configure ( String configFilename); </span><br><span class="line"></span><br><span class="line">//<span class="number">3</span>.读取XML形式的配置文件。</span><br><span class="line">DOMConfigurator.configure ( String filename );</span><br><span class="line"></span><br><span class="line">//<span class="number">4</span>.添加配置信息</span><br><span class="line">SimpleLayout simpleLayout = new SimpleLayout();</span><br><span class="line"></span><br><span class="line"> try {</span><br><span class="line"> FileAppender fa = new FileAppender(simpleLayout, <span class="string">"test.log"</span>);</span><br><span class="line"> logger.addAppender(fa);</span><br><span class="line"> logger.setLevel(Level.ERROR);</span><br><span class="line"></span><br><span class="line"> logger.error(Object obj );</span><br><span class="line"> } catch (IOException e1) {</span><br><span class="line"> //...</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p>
<p>四种方式任选其一</p>
<h1 id="3-_u63D2_u5165_u8BB0_u5F55_u4FE1_u606F_uFF08_u683C_u5F0F_u5316_u65E5_u5FD7_u4FE1_u606F_uFF09"><a href="#3-_u63D2_u5165_u8BB0_u5F55_u4FE1_u606F_uFF08_u683C_u5F0F_u5316_u65E5_u5FD7_u4FE1_u606F_uFF09" class="headerlink" title="3.插入记录信息(格式化日志信息)"></a>3.插入记录信息(格式化日志信息)</h1><p>当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方,其语法如下:<br><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">Logger.debug ( Object message ) ; </span><br><span class="line">Logger.info ( Object message ) ; </span><br><span class="line">Logger.warn ( Object message ) ; </span><br><span class="line">Logger.error ( Object message ) ;</span><br></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<![CDATA[<h1 id="1-_u5F97_u5230_u8BB0_u5F55_u5668"><a href="#1-_u5F97_u5230_u8BB0_u5F55_u5668" class="headerlink" title="1.得到记录器"></a>1.得到记录器</h1><p>使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:<br><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">public static Logger getLogger( String name),</span><br></pre></td></tr></table></figure></p>
<p>通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。]]>
</summary>
<category term="log" scheme="http://www.iwooto.com/tags/log/"/>
</entry>
<entry>
<title><![CDATA[maven项目多个module工程搭建]]></title>
<link href="http://www.iwooto.com/2016/01/30/maven%E9%A1%B9%E7%9B%AE%E5%A4%9A%E4%B8%AAmodule%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/"/>
<id>http://www.iwooto.com/2016/01/30/maven项目多个module工程搭建/</id>
<published>2016-01-30T06:42:58.000Z</published>
<updated>2016-01-30T09:04:23.987Z</updated>
<content type="html"><![CDATA[<h3 id="u521B_u5EFA_u7236_u5DE5_u7A0B"><a href="#u521B_u5EFA_u7236_u5DE5_u7A0B" class="headerlink" title="创建父工程"></a>创建父工程</h3><p>maven多模块项目需要一个父工程来聚合各个子模块,不过其实就是需要一个父pomxml,<br>主要作用是声明子模块,代码如下:<a id="more"></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><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"><project xmlns=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> xmlns:xsi=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span> xsi:schemaLocation=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span><br><span class="line"> <modelVersion><span class="number">4.0</span>.<span class="number">0</span></modelVersion> <!-- maven版本号--></span><br><span class="line"> <groupId>com.iwooto</groupId> <!-- maven包路径--></span><br><span class="line"> <artifactId>maventest</artifactId> <!-- maven包名--></span><br><span class="line"> <packaging>pom</packaging> <!-- maven父工程的packaging类型必须为pom--></span><br><span class="line"> <version><span class="variable">${project.version}</span></version> <!-- 项目版本--></span><br><span class="line"> <name>maventest</name> <!-- 项目名称--></span><br><span class="line"> <url>http://maven.apache.org</url> <!-- maven库--></span><br><span class="line"> <properties></span><br><span class="line"> <project.version><span class="number">0.0</span>.<span class="number">1</span></project.version></span><br><span class="line"> </properties></span><br><span class="line"> <modules></span><br><span class="line"> <module>mavenweb</module> <!-- 第一个web项目子模块--></span><br><span class="line"> <module>mavenadmin</module> <!-- 第二个web项目子模块--></span><br><span class="line"> <module>mavenjava</module> <!-- 第一个java项目子模块,当然也可以已打包的形式引入--></span><br><span class="line"> </modules></span><br><span class="line"> <dependencies> <!-- 父工程下面的所有子模块都会继承的引入下面的依赖包 --></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>junit</groupId></span><br><span class="line"> <artifactId>junit</artifactId></span><br><span class="line"> <version><span class="number">4.8</span>.<span class="number">1</span></version></span><br><span class="line"> <scope><span class="built_in">test</span></scope></span><br><span class="line"> </dependency></span><br><span class="line"> </dependencies></span><br><span class="line"> <dependencyManagement> <!-- 只有父工程会引入以下的依赖包,对子模块无影响--></span><br><span class="line"> <dependencies></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>mavenadmin</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"> <<span class="built_in">type</span>>war</<span class="built_in">type</span>></span><br><span class="line"> </dependency></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>mavenweb</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"> <<span class="built_in">type</span>>war</<span class="built_in">type</span>></span><br><span class="line"> </dependency></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>mavenjava</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"> </dependency> </span><br><span class="line"> </dependencies></span><br><span class="line"> </dependencyManagement></span><br><span class="line"></project></span><br></pre></td></tr></table></figure>
<h3 id="u521B_u5EFA_u5B50_u6A21_u5757_u5DE5_u7A0B"><a href="#u521B_u5EFA_u5B50_u6A21_u5757_u5DE5_u7A0B" class="headerlink" title="创建子模块工程"></a>创建子模块工程</h3><p>目录结构<br><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><br><span class="line"> |-- my-module1 </span><br><span class="line"> | `-- pom.xml 第一个web项目子模块</span><br><span class="line"> |-- my-module2</span><br><span class="line"> | `-- pom.xml 第二个web项目子模块</span><br><span class="line"> |-- my-module3</span><br><span class="line"> | `-- pom.xml 第一个java项目子模块</span><br><span class="line"> `-- pom.xml 父模块</span><br></pre></td></tr></table></figure></p>
<p>如果使用的是eclipse的话直接在父工程项目->右键->Maven->Add New Maven Module Project,剩下的和创建普通maven项目流程相同。</p>
<h1 id="u7B2C_u4E00_u4E2Aweb_u5B50_u6A21_u5757_28web_u9879_u76EE_u4E3B_u6A21_u5757_u5176_u4ED6web_u9879_u76EE_u4F1A_u6253_u5305_u5230_u8BE5_u6A21_u5757_29pom-xml_u4EE3_u7801"><a href="#u7B2C_u4E00_u4E2Aweb_u5B50_u6A21_u5757_28web_u9879_u76EE_u4E3B_u6A21_u5757_u5176_u4ED6web_u9879_u76EE_u4F1A_u6253_u5305_u5230_u8BE5_u6A21_u5757_29pom-xml_u4EE3_u7801" class="headerlink" title="第一个web子模块(web项目主模块其他web项目会打包到该模块)pom.xml代码"></a>第一个web子模块(web项目主模块其他web项目会打包到该模块)pom.xml代码</h1><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></pre></td><td class="code"><pre><span class="line"><project xmlns=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> xmlns:xsi=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span> xsi:schemaLocation=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span><br><span class="line"> <modelVersion><span class="number">4.0</span>.<span class="number">0</span></modelVersion></span><br><span class="line"> <parent></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>maventest</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"> </parent></span><br><span class="line"> <artifactId>mavenweb</artifactId></span><br><span class="line"> <packaging>war</packaging></span><br><span class="line"> <name>mavenweb</name></span><br><span class="line"> <url>http://maven.apache.org</url></span><br><span class="line"> <dependencies></span><br><span class="line"> <dependency> <!-- 被合并的子web项目,必须在主项目中添加依赖关系 --></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>mavenadmin</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"> <<span class="built_in">type</span>>war</<span class="built_in">type</span>></span><br><span class="line"> </dependency></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>mavenjava</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"> </dependency> </span><br><span class="line"> </dependencies></span><br><span class="line"> <build> </span><br><span class="line"> <finalName>maventest</finalName> </span><br><span class="line"> <plugins> </span><br><span class="line"> <!-- 合并多个war --> </span><br><span class="line"> <plugin> </span><br><span class="line"> <groupId>org.apache.maven.plugins</groupId> </span><br><span class="line"> <artifactId>maven-war-plugin</artifactId> </span><br><span class="line"> <configuration> </span><br><span class="line"> <!-- 过滤其他模块的web.xml文件 --></span><br><span class="line"> <packagingExcludes>WEB-INF/web.xml</packagingExcludes> </span><br><span class="line"> <overlays> </span><br><span class="line"> <overlay> </span><br><span class="line"> <groupId>com.iwooto</groupId> </span><br><span class="line"> <artifactId>mavenadmin</artifactId> </span><br><span class="line"> </overlay> </span><br><span class="line"> </overlays> </span><br><span class="line"> </configuration> </span><br><span class="line"> </plugin> </span><br><span class="line"> </plugins></span><br><span class="line"> <!-- 配置项目的资源文件,可以是多个项目下的资源文件 --> </span><br><span class="line"> <resources></span><br><span class="line"> <resource></span><br><span class="line"> <directory>../mavenadmin/src/main/resources</directory></span><br><span class="line"> <excludes> </span><br><span class="line"> <exclude>config/**</exclude> </span><br><span class="line"> </excludes> </span><br><span class="line"> </resource></span><br><span class="line"> <resource></span><br><span class="line"> <directory>src/main/resources</directory></span><br><span class="line"> </resource></span><br><span class="line"> </resources> </span><br><span class="line"> </build> </span><br><span class="line"></project></span><br></pre></td></tr></table></figure>
<h1 id="u7B2C_u4E8C_u4E2Aweb_u5B50_u6A21_u5757_28_u8BE5_u6A21_u5757_u4F1A_u6253_u5305_u5230web_u4E3B_u6A21_u5757_u4E2D_29pom-xml_u4EE3_u7801"><a href="#u7B2C_u4E8C_u4E2Aweb_u5B50_u6A21_u5757_28_u8BE5_u6A21_u5757_u4F1A_u6253_u5305_u5230web_u4E3B_u6A21_u5757_u4E2D_29pom-xml_u4EE3_u7801" class="headerlink" title="第二个web子模块(该模块会打包到web主模块中)pom.xml代码"></a>第二个web子模块(该模块会打包到web主模块中)pom.xml代码</h1><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></pre></td><td class="code"><pre><span class="line"><project xmlns=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> xmlns:xsi=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span> xsi:schemaLocation=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span><br><span class="line"> <modelVersion><span class="number">4.0</span>.<span class="number">0</span></modelVersion></span><br><span class="line"> <parent></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>maventest</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"> </parent></span><br><span class="line"> <artifactId>mavenadmin</artifactId></span><br><span class="line"> <packaging>war</packaging></span><br><span class="line"> <name>mavenadmin</name></span><br><span class="line"> <url>http://maven.apache.org</url></span><br><span class="line"> <build> </span><br><span class="line"> <plugins> </span><br><span class="line"> <plugin> </span><br><span class="line"> <groupId>org.apache.maven.plugins</groupId> </span><br><span class="line"> <artifactId>maven-war-plugin</artifactId> </span><br><span class="line"> <configuration> </span><br><span class="line"> <!-- 如果该模块没有web.xml文件的话,要进行一下声明 --></span><br><span class="line"> <failOnMissingWebXml><span class="literal">false</span></failOnMissingWebXml> </span><br><span class="line"> </configuration> </span><br><span class="line"> </plugin> </span><br><span class="line"> </plugins> </span><br><span class="line"> </build> </span><br><span class="line"></project></span><br></pre></td></tr></table></figure>
<h1 id="u7B2C_u4E00_u4E2Ajava_u5B50_u6A21_u5757pom-xml_u4EE3_u7801"><a href="#u7B2C_u4E00_u4E2Ajava_u5B50_u6A21_u5757pom-xml_u4EE3_u7801" class="headerlink" title="第一个java子模块pom.xml代码"></a>第一个java子模块pom.xml代码</h1><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"><project xmlns=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> xmlns:xsi=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span> xsi:schemaLocation=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span><br><span class="line"> <modelVersion><span class="number">4.0</span>.<span class="number">0</span></modelVersion></span><br><span class="line"> <parent></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>maventest</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"> </parent></span><br><span class="line"> <artifactId>mavenjava</artifactId></span><br><span class="line"> <name>mavenjava</name> </span><br><span class="line"></project></span><br></pre></td></tr></table></figure>
<h3 id="web_u9879_u76EE_u5408_u5E76_u5F53_u7740_u9700_u8981_u6CE8_u610F_u4E00_u4E0B_u8BB0_u5F97"><a href="#web_u9879_u76EE_u5408_u5E76_u5F53_u7740_u9700_u8981_u6CE8_u610F_u4E00_u4E0B_u8BB0_u5F97" class="headerlink" title="web项目合并当着需要注意一下记得"></a>web项目合并当着需要注意一下记得</h3><ol>
<li>被合并的子web项目packaging属性必须是war</li>
<li>被合并的子web项目,必须在主项目中添加依赖关系。</li>
<li>被合并的子web项目中,如果没有web.xml,则需要在pom.xml中声明</li>
<li>在web项目主模块中的java build path 中添加子web项目的依赖,就可以直接调用子项目的方法咯(记得避免循环依赖哦)</li>
<li>被合并的子web项目中的web.xml你可以选择性的放入合并内容当中(可以看情况需要进行合并)</li>
<li>配置文件继承相同的继承策略用于为 POM 本身。<br>只要配置好以上内容,该多个模块的maven项目的主web模块就可以放到tomcat中运行起来啦。</li>
</ol>
<h1 id="u6DFB_u52A0_u4EE5_u524D_u7684_u9879_u76EE_u4F5C_u4E3A_u5B50_u6A21_u5757_u5230_u65B0_u7684_u9879_u76EE_u5F53_u4E2D"><a href="#u6DFB_u52A0_u4EE5_u524D_u7684_u9879_u76EE_u4F5C_u4E3A_u5B50_u6A21_u5757_u5230_u65B0_u7684_u9879_u76EE_u5F53_u4E2D" class="headerlink" title="添加以前的项目作为子模块到新的项目当中"></a>添加以前的项目作为子模块到新的项目当中</h1><p>其实只需要修改一下父工程pom.xml引用子模块的pom.xml文件的路径<br>和子模块引用pom.xml引用父工程的pom.xml的路径就可以啦<br>父工程与子模块平级的情况<br>目录结构<br><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">.</span><br><span class="line">|-- my-module1</span><br><span class="line">| `-- pom.xml</span><br><span class="line">|-- my-module2</span><br><span class="line">| `-- pom.xml</span><br><span class="line">|-- my-module3</span><br><span class="line">| `-- pom.xml</span><br><span class="line"> `-- parent</span><br><span class="line"> `-- pom.xml</span><br></pre></td></tr></table></figure></p>
<p>父工程pom.xml修改如下内容:<br>修改前:<br><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"><modules></span><br><span class="line"> <module>mavenweb</module> <!-- 第一个web项目子模块--></span><br><span class="line"> <module>mavenadmin</module> <!-- 第二个web项目子模块--></span><br><span class="line"> <module>mavenjava</module> <!-- 第一个java项目子模块,当然也可以已打包的形式引入--></span><br><span class="line"></modules></span><br></pre></td></tr></table></figure></p>
<p>修改后:<br><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"><modules></span><br><span class="line"> <module>../mavenweb</module> <!-- 第一个web项目子模块--></span><br><span class="line"> <module>../mavenadmin</module> <!-- 第二个web项目子模块--></span><br><span class="line"> <module>../mavenjava</module> <!-- 第一个java项目子模块,当然也可以已打包的形式引入--></span><br><span class="line"></modules></span><br></pre></td></tr></table></figure></p>
<p>子模块pom.xml修改以下内容:<br>修改前:<br><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"><parent></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>maventest</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"></parent></span><br></pre></td></tr></table></figure></p>
<p>修改后:<br><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"><parent></span><br><span class="line"> <groupId>com.iwooto</groupId></span><br><span class="line"> <artifactId>../maventest</artifactId></span><br><span class="line"> <version><span class="variable">${project.version}</span></version></span><br><span class="line"></parent></span><br></pre></td></tr></table></figure></p>
<p>项目改造就完成啦。<a href="https://github.com/WhyNotRunning/maventest" target="_blank" rel="external">我的demo地址</a></p>
]]></content>
<summary type="html">
<![CDATA[<h3 id="u521B_u5EFA_u7236_u5DE5_u7A0B"><a href="#u521B_u5EFA_u7236_u5DE5_u7A0B" class="headerlink" title="创建父工程"></a>创建父工程</h3><p>maven多模块项目需要一个父工程来聚合各个子模块,不过其实就是需要一个父pomxml,<br>主要作用是声明子模块,代码如下:]]>
</summary>
<category term="maven" scheme="http://www.iwooto.com/tags/maven/"/>
</entry>
<entry>
<title><![CDATA[hexo博客搭建过程]]></title>
<link href="http://www.iwooto.com/2016/01/12/hexo%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA%E8%BF%87%E7%A8%8B/"/>
<id>http://www.iwooto.com/2016/01/12/hexo博客搭建过程/</id>
<published>2016-01-12T13:39:41.000Z</published>
<updated>2016-02-01T13:23:42.448Z</updated>
<content type="html"><![CDATA[<h3 id="u8F6F_u4EF6_u5B89_u88C5"><a href="#u8F6F_u4EF6_u5B89_u88C5" class="headerlink" title="软件安装"></a>软件安装</h3><p>1.nodejs<br>2.git<a id="more"></a></p>
<h3 id="u521B_u5EFAgit_pages"><a href="#u521B_u5EFAgit_pages" class="headerlink" title="创建git pages"></a>创建git pages</h3><p>在github新建一个仓库,Github Pages 的仓库名必须为your_user_name.github.io<br>获取git的ssh<br><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">$ ssh-keygen -c <span class="string">"youremail@163.com"</span> <span class="comment">#连点三次</span></span><br></pre></td></tr></table></figure></p>
<p>找到C:\Users\Administrator.ssh\id_rsa.pub 文件打开,复制里面内容添加到自己的github的sshkeys 中(新建一个add sshkey)</p>
<h3 id="Hexo"><a href="#Hexo" class="headerlink" title="Hexo"></a>Hexo</h3><p>安装Hexo<br><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">npm install -g hexo</span><br><span class="line">npm install -g hexo-cli</span><br></pre></td></tr></table></figure></p>
<p>查看Hexo版本<br><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">hexo v</span><br></pre></td></tr></table></figure></p>
<p>创建Hexo项目<br><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">hexo init myHexo</span><br></pre></td></tr></table></figure></p>
<p>进入项目初始化<br><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> myHexo</span><br><span class="line">hexo init</span><br></pre></td></tr></table></figure></p>
<p>安装依赖包<br><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">npm install</span><br></pre></td></tr></table></figure></p>
<p>启动服务<br><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">hexo server</span><br><span class="line">或</span><br><span class="line">hexo s</span><br></pre></td></tr></table></figure></p>
<p>用浏览器打开<a href="http://localhost:4000/或者http://127.0.0.1:4000/就能看到网页了" target="_blank" rel="external">http://localhost:4000/或者http://127.0.0.1:4000/就能看到网页了</a></p>
<h3 id="u76EE_u5F55_u7ED3_u6784"><a href="#u76EE_u5F55_u7ED3_u6784" 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></pre></td><td class="code"><pre><span class="line">├── .deploy <span class="comment">#需要部署的文件</span></span><br><span class="line">├── node_modules <span class="comment">#Hexo插件</span></span><br><span class="line">├── public <span class="comment">#生成的静态网页文件</span></span><br><span class="line">├── scaffolds <span class="comment">#模板</span></span><br><span class="line">├── <span class="built_in">source</span> <span class="comment">#博客正文和其他源文件,404、favicon、CNAME 都应该放在这里</span></span><br><span class="line">| ├── _drafts <span class="comment">#草稿</span></span><br><span class="line">| └── _posts <span class="comment">#文章</span></span><br><span class="line">├── themes <span class="comment">#主题</span></span><br><span class="line">├── _config.yml <span class="comment">#全局配置文件</span></span><br><span class="line">└── package.json</span><br></pre></td></tr></table></figure>
<h3 id="u5168_u5C40_u7684_config-yml_u6587_u4EF6_u914D_u7F6E"><a href="#u5168_u5C40_u7684_config-yml_u6587_u4EF6_u914D_u7F6E" class="headerlink" title="全局的_config.yml文件配置"></a>全局的_config.yml文件配置</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><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"><span class="comment"># Hexo Configuration</span></span><br><span class="line"><span class="comment">## Docs: http://hexo.io/docs/configuration.html</span></span><br><span class="line"><span class="comment">## Source: https://github.com/hexojs/hexo/</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Site</span></span><br><span class="line">title: pangyalin的博客</span><br><span class="line">subtitle: pangyalin的博客 </span><br><span class="line">description: pangyalin的博客 <span class="comment">#站点描述</span></span><br><span class="line">author: pyl <span class="comment">#作者</span></span><br><span class="line">language: zh-Hans <span class="comment">#语音</span></span><br><span class="line">timezone: <span class="comment">#时区</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># URL</span></span><br><span class="line"><span class="comment">## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'</span></span><br><span class="line">url: http://iwooto.com</span><br><span class="line">root: /</span><br><span class="line">permalink: :year/:month/:day/:title/ <span class="comment">#文章的链接格式</span></span><br><span class="line">permalink_defaults:</span><br><span class="line"></span><br><span class="line"><span class="comment"># Directory 目录</span></span><br><span class="line"><span class="built_in">source</span>_dir: <span class="built_in">source</span> <span class="comment">#源文件目录</span></span><br><span class="line">public_dir: public <span class="comment">#生成文件目录</span></span><br><span class="line">tag_dir: tags <span class="comment">#tag标签目录</span></span><br><span class="line">archive_dir: archives <span class="comment">#文章目录</span></span><br><span class="line">category_dir: categories <span class="comment">#分类目录</span></span><br><span class="line">code_dir: downloads/code <span class="comment">#code目录</span></span><br><span class="line">i18n_dir: :lang</span><br><span class="line">skip_render:</span><br><span class="line"></span><br><span class="line"><span class="comment"># Writing 写作</span></span><br><span class="line">new_post_name: :title.md <span class="comment"># File name of new posts 新建文章</span></span><br><span class="line">default_layout: post <span class="comment">#默认的模板,包括 post、page、photo、draft(文章、页面、照片、草稿)</span></span><br><span class="line">titlecase: <span class="literal">false</span> <span class="comment"># Transform title into titlecase 标题转换大小写</span></span><br><span class="line">external_link: <span class="literal">true</span> <span class="comment"># Open external links in new tab 是否打开新的标签页</span></span><br><span class="line">filename_<span class="keyword">case</span>: <span class="number">0</span> </span><br><span class="line">render_drafts: <span class="literal">false</span></span><br><span class="line">post_asset_folder: <span class="literal">false</span></span><br><span class="line">relative_link: <span class="literal">false</span></span><br><span class="line">future: <span class="literal">true</span></span><br><span class="line">highlight: <span class="comment">#语法高亮</span></span><br><span class="line"> <span class="built_in">enable</span>: <span class="literal">true</span> <span class="comment">#是否启用</span></span><br><span class="line"> line_number: <span class="literal">true</span> <span class="comment">#是否显示行号</span></span><br><span class="line"> auto_detect: <span class="literal">true</span> <span class="comment">#自动检测</span></span><br><span class="line"> tab_replace: <span class="comment">#tab替换</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Category & Tag 分类与标签</span></span><br><span class="line">default_category: uncategorized</span><br><span class="line">category_map:</span><br><span class="line">tag_map:</span><br><span class="line"></span><br><span class="line"><span class="comment"># Date / Time format 日期格式</span></span><br><span class="line"><span class="comment">## Hexo uses Moment.js to parse and display date</span></span><br><span class="line"><span class="comment">## You can customize the date format as defined in</span></span><br><span class="line"><span class="comment">## http://momentjs.com/docs/#/displaying/format/</span></span><br><span class="line">date_format: YYYY-MM-DD</span><br><span class="line">time_format: HH:mm:ss</span><br><span class="line"></span><br><span class="line"><span class="comment"># Pagination 分页</span></span><br><span class="line"><span class="comment">## Set per_page to 0 to disable pagination 设置0时不进行分页</span></span><br><span class="line">per_page: <span class="number">10</span> 每页显示文章条数</span><br><span class="line">pagination_dir: page</span><br><span class="line"></span><br><span class="line"><span class="comment"># Extensions 拓展</span></span><br><span class="line"><span class="comment">## Plugins: http://hexo.io/plugins/ 插件设置</span></span><br><span class="line">plugins: </span><br><span class="line"> hexo-generator-feed</span><br><span class="line"> hexo-generator-sitemap </span><br><span class="line"><span class="comment">## Themes: http://hexo.io/themes/ 主题设置</span></span><br><span class="line">theme: yilia</span><br><span class="line"></span><br><span class="line"><span class="comment"># Deployment 部署到服务器</span></span><br><span class="line"><span class="comment">## Docs: http://hexo.io/docs/deployment.html</span></span><br><span class="line">deploy:</span><br><span class="line"> <span class="built_in">type</span>: git <span class="comment">#hexo 3.1 以后改github 为 git</span></span><br><span class="line"> repository: git@github.com:WhyNotRunning/WhyNotRunning.github.io.git</span><br><span class="line"> branch: master</span><br></pre></td></tr></table></figure>
<h3 id="hexo_u547D_u4EE4_u4F7F_u7528"><a href="#hexo_u547D_u4EE4_u4F7F_u7528" class="headerlink" title="hexo命令使用"></a>hexo命令使用</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">hexo clean <span class="comment">#Removed generated files and cache.删除自动生成的文件和清除缓存。</span></span><br><span class="line">hexo config <span class="comment">#Get or set configurations.获取和设置hexo配置</span></span><br><span class="line">hexo deploy <span class="comment">#Deploy your website. 发布到你的站点</span></span><br><span class="line">hexo generate <span class="comment">#Generate static files.自动生成静态文件</span></span><br><span class="line">hexo <span class="built_in">help</span> <span class="comment">#Get help on a command.获取hexo帮助</span></span><br><span class="line">hexo init <span class="comment">#Create a new Hexo folder.初始化生成一个hexo目录</span></span><br><span class="line">hexo list <span class="comment">#List the information of the site显示站点的信息</span></span><br><span class="line">hexo migrate <span class="comment">#Migrate your site from other system to Hexo.从其他hexo系统复制</span></span><br><span class="line">hexo new <span class="comment">#Create a new post.新建一篇文章</span></span><br><span class="line">hexo publish <span class="comment">#Moves a draft post from _drafts to _posts folder.发布草稿文章</span></span><br><span class="line">hexo render <span class="comment">#Render files with renderer plugins.</span></span><br><span class="line">hexo server <span class="comment">#Start the server.启动本地服务</span></span><br><span class="line">hexo version <span class="comment">#Display version information.查看版本</span></span><br></pre></td></tr></table></figure>
<p>hexo命令简写hexo + 命令首字母<br><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">hexo c ==> hexo clean</span><br></pre></td></tr></table></figure></p>
<h3 id="u65B0_u5EFA_u4E00_u7BC7_u535A_u5BA2"><a href="#u65B0_u5EFA_u4E00_u7BC7_u535A_u5BA2" 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">hexo new <span class="string">"博客名称"</span></span><br></pre></td></tr></table></figure>
<p>找到source/_post/博客名称.md进行编辑</p>
<h3 id="u5B89_u88C5_u63D2_u4EF6"><a href="#u5B89_u88C5_u63D2_u4EF6" class="headerlink" title="安装插件"></a>安装插件</h3><p>生成rss<br><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">npm install hexo-generator-feed --save-dev</span><br></pre></td></tr></table></figure></p>
<p>生成网站地图<br><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">npm install hexo-generator-sitemap --save-dev</span><br></pre></td></tr></table></figure></p>
<p>-save和save-dev可以省掉你手动修改package.json文件的步骤。<br><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">npm install module-name -save 自动把模块和版本号添加到dependencies部分</span><br><span class="line">npm install module-name -save-dve 自动把模块和版本号添加到devdependencies部分</span><br></pre></td></tr></table></figure></p>
<h3 id="hexo_u53D1_u5E03_u62A5_u9519"><a href="#hexo_u53D1_u5E03_u62A5_u9519" class="headerlink" title="hexo发布报错"></a>hexo发布报错</h3><p>执行 hexo d 报错<br><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">Error: spawn git ENOENT</span><br><span class="line"> at exports._errnoException (util.js:<span class="number">746</span>:<span class="number">11</span>)</span><br><span class="line"> at Process.ChildProcess._handle.onexit (child_process.js:<span class="number">1053</span>:<span class="number">32</span>)</span><br><span class="line"> at child_process.js:<span class="number">1144</span>:<span class="number">20</span></span><br><span class="line"> at process._tickCallback (node.js:<span class="number">355</span>:<span class="number">11</span>)</span><br></pre></td></tr></table></figure></p>
<p>hexo提交必须通过git bash上才可以提交</p>
<h3 id="npm_u6DD8_u5B9D_u955C_u50CF_u4F7F_u7528"><a href="#npm_u6DD8_u5B9D_u955C_u50CF_u4F7F_u7528" class="headerlink" title="npm淘宝镜像使用"></a>npm淘宝镜像使用</h3><p>你可以使用我们定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:<br><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">$ npm install -g cnpm --registry=https://registry.npm.taobao.org</span><br></pre></td></tr></table></figure></p>
<p><a href="http://npm.taobao.org/" target="_blank" rel="external">淘宝 NPM 镜像</a></p>
]]></content>
<summary type="html">
<![CDATA[<h3 id="u8F6F_u4EF6_u5B89_u88C5"><a href="#u8F6F_u4EF6_u5B89_u88C5" class="headerlink" title="软件安装"></a>软件安装</h3><p>1.nodejs<br>2.git]]>
</summary>
<category term="hexo" scheme="http://www.iwooto.com/tags/hexo/"/>
</entry>
<entry>
<title><![CDATA[再次认识js的立即执行函数]]></title>
<link href="http://www.iwooto.com/2016/01/10/%E9%87%8D%E6%96%B0%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2/"/>
<id>http://www.iwooto.com/2016/01/10/重新搭建博客/</id>
<published>2016-01-10T14:14:00.000Z</published>
<updated>2016-01-30T05:15:43.038Z</updated>
<content type="html"><![CDATA[<h3 id="u4ECEES3_u662F_u5982_u4F55_u89E3_u6790js_u7684_u8FC7_u7A0B_u7406_u89E3"><a href="#u4ECEES3_u662F_u5982_u4F55_u89E3_u6790js_u7684_u8FC7_u7A0B_u7406_u89E3" class="headerlink" title="从ES3是如何解析js的过程理解"></a>从ES3是如何解析js的过程理解</h3><p>1.首先函数的正确声明结构是怎样的<br>2.表达式的声明方式,和如何构成表达式<a id="more"></a><br>错误实例1:意图声明一个函数,并且立即调用改函数<br><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="function"><span class="title">function</span></span>(){}()</span><br></pre></td></tr></table></figure></p>
<p>错误原因:函数必须有函数名</p>
<p>错误实例2:声明一个函数,并且立即调用改函数<br><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="keyword">function</span> <span class="function"><span class="title">fun</span></span>(){}()</span><br></pre></td></tr></table></figure></p>
<p>错误原因:最后面的那一组小括号被当做分组运算符,并没有被解析成调用fun函数</p>
<p>正确实例:通过常用的运算符如()、!、—、+、typeof等放在匿名函数前,<br>让解析器把后面的函数当做表达式执行再通过()调用该函数<br><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="function"><span class="title">function</span></span>(){</span><br><span class="line">}())</span><br></pre></td></tr></table></figure></p>
<p>我的<a href="http://www.iwooto.com">博客地址</a></p>
]]></content>
<summary type="html">
<![CDATA[<h3 id="u4ECEES3_u662F_u5982_u4F55_u89E3_u6790js_u7684_u8FC7_u7A0B_u7406_u89E3"><a href="#u4ECEES3_u662F_u5982_u4F55_u89E3_u6790js_u7684_u8FC7_u7A0B_u7406_u89E3" class="headerlink" title="从ES3是如何解析js的过程理解"></a>从ES3是如何解析js的过程理解</h3><p>1.首先函数的正确声明结构是怎样的<br>2.表达式的声明方式,和如何构成表达式]]>
</summary>
<category term="js" scheme="http://www.iwooto.com/tags/js/"/>
</entry>
</feed>