-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathatom.xml
7226 lines (6048 loc) · 574 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
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[葱丝瓣酱]]></title>
<link href="http://xiaocong.github.io/atom.xml" rel="self"/>
<link href="http://xiaocong.github.io/"/>
<updated>2014-03-02T21:42:17+08:00</updated>
<id>http://xiaocong.github.io/</id>
<author>
<name><![CDATA[Xiaocong He]]></name>
<email><![CDATA[[email protected]]]></email>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Android uiautomator的python包]]></title>
<link href="http://xiaocong.github.io/blog/2013/08/26/android-uiautomator-and-python/"/>
<updated>2013-08-26T17:59:00+08:00</updated>
<id>http://xiaocong.github.io/blog/2013/08/26/android-uiautomator-and-python</id>
<content type="html"><![CDATA[<p>随着Android的快速演进,先后经历了 Android 测试框架从 InstrumentationTest, Robotium, Monkeyrunner, 直到 uiautomator 的变化,从目前来看,对于独立的QA团队来说,uiautomator 是最适合的 Android 测试框架.</p>
<p>就我个人的体会,沉重的 Java 语言及其繁琐的工具链,是阻碍 uiautomator 推广的障碍,个人更喜欢 Python 和 Javascript 的快速开发和方便的工具链。为了更方便地利用 uiautomator,花了两周时间实现了 Android uiautomator 的 Python Wrapper 模块并开源出来:</p>
<ul>
<li><a href="https://pypi.python.org/pypi/uiautomator">pypi: uiautomator</a></li>
<li><a href="http://xiaocong.github.io/slides/android-uiautomator-and-python/">uiautomator.py slides</a></li>
<li><a href="https://github.com/xiaocong/uiautomator">github source code</a></li>
</ul>
<p>希望下一步能有时间完成相应的 nodejs 模块。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[符合语言习惯的Python编程]]></title>
<link href="http://xiaocong.github.io/blog/2013/07/18/idiomatic-python-code/"/>
<updated>2013-07-18T12:02:00+08:00</updated>
<id>http://xiaocong.github.io/blog/2013/07/18/idiomatic-python-code</id>
<content type="html"><![CDATA[<p>给 Team 内部培训用的 Slides:<a href="http://xiaocong.github.io/slides/idiomatic-python-code/">符合语言习惯的Python编程</a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[在Ubuntu下配置舒服的Python开发环境]]></title>
<link href="http://xiaocong.github.io/blog/2013/06/18/customize-python-dev-environment-on-ubuntu/"/>
<updated>2013-06-18T14:37:00+08:00</updated>
<id>http://xiaocong.github.io/blog/2013/06/18/customize-python-dev-environment-on-ubuntu</id>
<content type="html"><![CDATA[<p>Ubuntu 提供了一个良好的 Python 开发环境,但如果想使我们的开发效率最大化,还需要进行很多定制化的安装和配置。下面的是我们团队开发人员推荐的一个安装和配置步骤,基于 Ubuntu 12.04 桌面版本标准安装。</p>
<h2>安装 Python 发布版本和 build 依赖包</h2>
<p>建议至少安装 Python 2.7/3.2 版本,毕竟 Python 2.X/3.X 还是有不少区别的。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c"># 安装 Python 发布版本,dev包必须安装,很多用pip安装包都需要编译</span>
</span><span class='line'>sudo apt-get install python2.7 python2.7-dev python3.2 python3.2-dev
</span><span class='line'><span class="c"># 很多pip安装的包都需要libssl和libevent编译环境</span>
</span><span class='line'>sudo apt-get install build-essential libssl-dev libevent-dev libjpeg-dev libxml2-dev libxslt-dev
</span></code></pre></td></tr></table></div></figure>
<!--more-->
<h2>安装 pip 和 virtualenv</h2>
<p><code>pip</code> 是 Python 的包管理工具,建议 Python 的包都用 pip 进行管理。<code>virtualenv</code>是 Python 多版本管理的利器,不同版本的开发调试全靠它了。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c"># 安装 pip</span>
</span><span class='line'>sudo apt-get install python-pip
</span><span class='line'><span class="c"># 安装 virtualenv</span>
</span><span class='line'>sudo pip install virtualenv
</span></code></pre></td></tr></table></div></figure>
<h2>配置个人用 virtualenv</h2>
<p>尽量在 virtualenv 下进行 Python 包的安装。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c"># 安装 python2.7 virtualenv</span>
</span><span class='line'>virtualenv --no-site-packages -p /usr/bin/python2.7 ~/.venv/python2.7
</span><span class='line'>
</span><span class='line'><span class="c"># 安装 python3.2 virtualenv</span>
</span><span class='line'>virtualenv --no-site-packages -p /usr/bin/python3.2 ~/.venv/python3.2
</span></code></pre></td></tr></table></div></figure>
<p>然后将下面的代码增加到<code>~/.bashrc</code>的最后面,缺省使用 virtualenv 来代替系统 Python 环境:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c"># 缺省激活python2.7环境</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -f ~/.venv/python2.7/bin/activate <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'> . ~/.venv/python2.7/bin/activate
</span><span class='line'><span class="k">fi</span>
</span></code></pre></td></tr></table></div></figure>
<h2>安装 git 和 gitflow</h2>
<p><code>git</code>是使用 github 必备,目前最好的版本管理工具。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>sudo apt-get install git
</span></code></pre></td></tr></table></div></figure>
<p>配置 git:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c"># 常用的命令都设置alias,尽量少敲键盘</span>
</span><span class='line'>git config --global alias.br branch
</span><span class='line'>git config --global alias.ci commit
</span><span class='line'>git config --global alias.co checkout
</span><span class='line'>git config --global alias.st status
</span><span class='line'><span class="c"># 很好看地显示git log</span>
</span><span class='line'>git config --global alias.lg <span class="s2">"log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen (%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --"</span>
</span><span class='line'><span class="c"># 设置用户信息</span>
</span><span class='line'>git config --global user.name <span class="s2">"Your Name"</span>
</span><span class='line'>git config --global user.email [email protected]
</span><span class='line'><span class="c"># 缺省使用颜色显示</span>
</span><span class='line'>git config --global color.ui <span class="nb">true</span>
</span></code></pre></td></tr></table></div></figure>
<p>安装 <code>git-flow</code>,使用标准化 git 分支流程,参见:</p>
<ul>
<li><a href="http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/">使用 Git Flow</a></li>
<li><a href="http://nvie.com/posts/a-successful-git-branching-model/">一个成功的 Git 分支模型</a></li>
</ul>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>sudo apt-get install git-flow
</span></code></pre></td></tr></table></div></figure>
<h2>安装 bash-it</h2>
<p><code>bash-it</code>可以美化你的 bash 环境,让你更高效地使用控制台终端,详细信息参见<a href="https://github.com/revans/bash-it">bash-it github 网站</a></p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>git clone http://github.com/revans/bash-it.git ~/.bash_it
</span><span class='line'>~/.bash_it/install.sh
</span></code></pre></td></tr></table></div></figure>
<p>安装的时候可以选择所有的 alias/plugins/completion,如果自定义选择,一定将<code>virtualenv</code>, <code>git</code>插件选择上。</p>
<p>安装完成后将下面的代码附加到<code>~/.bashrc</code>的后面:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="k">if</span> <span class="o">[</span> -f ~/.bash_profile <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'> . ~/.bash_profile
</span><span class='line'><span class="k">fi</span>
</span></code></pre></td></tr></table></div></figure>
<p><code>bash-it</code>安装完成后缺省使用 bobby 样式(可以参见<code>~/.bash_profile</code>里定义的环境变量<code>BASH_IT_THEME</code>),编辑<code>~/.bash_it/themes/bobby/bobby.theme.bash</code>,在<code>PS1</code>的定义里增加<code>${green}$(virtualenv_prompt)</code>,如下:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">PS1</span><span class="o">=</span><span class="s2">"\n${yellow}$(ruby_version_prompt)${green}$(virtualenv_prompt) ${purple}\h ${reset_color}in ${green}\w\n${bold_cyan}$(scm_char)${green}$(scm_prompt_info) ${green}→${reset_color} "</span>
</span></code></pre></td></tr></table></div></figure>
<p>注:样式定义参加文件<code>~/.bash_profile</code>里定义的环境变量<code>BASH_IT_THEME</code>,你也将其值更改成其他<code>~/.bash_it/themes</code>里定义的样式。</p>
<p>最后重启终端,你将看到一个不一样的<code>bash</code>,支持显示<code>git</code>分支,<code>virtualenv</code>,<code>rvm</code>等。</p>
<h2>安装 Sublime Text 2</h2>
<p>在浏览器进入 <a href="http://www.sublimetext.com/2">Sublime Text 2 官网</a>,选择适合的版本下载安装。</p>
<p>安装完成后还需要安装<code>Sublime Text 2</code>的<code>Package Control</code>。安装细节参见 <a href="http://wbond.net/sublime_packages/package_control/installation">Sublime Packages 安装</a>。</p>
<p>最后,按快捷键<code>Ctrl+Shift+P</code>调出命令窗口,选择<code>Package Control: Install Package</code>,安装 Python 开发常用的插件:</p>
<ul>
<li>Auto Encoding for Python</li>
<li>BracketHighlighter</li>
<li>Git</li>
<li>Markdown Preview</li>
<li>Python Auto-Complete</li>
<li>SublimeLinter</li>
<li>SidebarEnhancements</li>
<li>SublimeCondeIntel</li>
<li>sublime-github</li>
<li>Dayle Rees Color Schemes</li>
</ul>
<p>这里推荐一下插件 sublime-github,能在 Sublime 里查看,增加,修改<a href="https://gist.github.com">GitHub Gist</a>。如果你和团队都使用 Github Gist 来存储自己常用的代码片段,这将非常方便大家去迅速查找和共享解决常见问题的代码片段。</p>
<ul>
<li>首先进入<a href="https://github.com/settings/applications">github</a> 新建一个个人 API 访问 token;</li>
<li>运行 Sublime,选择菜单<code>Preferences</code>–><code>Package Settings</code>–><code>GitHub</code>–><code>Settings-Default</code>,将上面生成的<code>token</code>复制到
<code>github_token</code>字段,保存。</li>
</ul>
<p>之后你就可以按快捷键<code>Ctrl+Shift+P</code>,选择<code>GitHub: Open Gist in Editor</code>,然后选择你自己的 Gist 即可。</p>
<h2>安装并配置 Vim</h2>
<p>有了 Sublime Text,大部分情况下都不需要 Vi 了,但的确有些时候进行很小的改动还是用 Vi 最方便。Ubuntu的缺省安装应当已经包括了 Vim,如果没有,运行下面命令安装 Vim。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>sudo apt-get install vim
</span></code></pre></td></tr></table></div></figure>
<p>然后,参考<a href="https://github.com/amix/vimrc">Amix’s Vimrc</a>来配置 Vim。</p>
<hr />
<p>至此,所有的基本环境就已经配备完成,希望这些配置能对大家有所帮助,下面是配置好的界面截屏。</p>
<p><img src="http://xiaocong.github.io/images/post/bash.png"></p>
<p><img src="http://xiaocong.github.io/images/post/sublime.png"></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Python 面试问题]]></title>
<link href="http://xiaocong.github.io/blog/2013/06/16/python-interview-question-and-answer/"/>
<updated>2013-06-16T12:36:00+08:00</updated>
<id>http://xiaocong.github.io/blog/2013/06/16/python-interview-question-and-answer</id>
<content type="html"><![CDATA[<p>最近正在团队内部普及 Python 语言,有些刚接触 Python 语言的工程师在概念上有很多混淆的地方,刚好看到这篇文章:<a href="http://ilian.i-n-i.org/python-interview-question-and-answers/">Python面试问题</a>,里面列举的问题都是关于 Python 基本的常识或者容易混淆的知识点,因此推荐给团队的 Python 初学者。</p>
<!--more-->
<ol>
<li><p>参数是如何传递的?传值还是传引用?(How are arguments passed – by reference of by value?)</p>
<p>这个问题的有点c/c++风格,问题的实质是当一个传入的参数在函数体内被更改,那么在函数返回后,函数体外的这个参数变量的值是否改变。最简短的回答是,”都不是”,事实上 Python 里是传对象(call by object)。</p>
<p>要弄明白这个变量的值是否在函数体外发生变化,需要明白两个概念:</p>
<ul>
<li>Python 里的对象分为有可变(mutable)和不可变(immutable):数字(int, float),字符串,元组(tuple)是不可变的,列表(list),字典(dict)是可变的。</li>
<li>所有的变量都是一个对象的引用。无论对象是否可变,这个变量都可被赋值为另外一个对象。</li>
</ul>
<p>因此,如果传入的参数变量指向一个不可变对象,那么在函数体外这个对象的内容永远不会发生变化;如果当传入的参数变量指向一个可变对象,那么这个对象是否发生变化,取决于函数体内部是否改变了这个可变对象的内容。</p>
<p>下面的例子里,<code>changed</code>函数调用改变了传入对象的内容,<code>unchanged</code>函数将<code>l</code>变量赋值为一个新生成的对象<code>l = l + ["a"]</code>,但原始对象并未发生变化:</p>
<pre><code>def changed(l):
l.append("a") # change the original object
def unchanged(l):
l = l + ["a"] # l + ["a"] will create a new list, instead of changing the original object
l1 = []
changed(l1)
# l1 == ["a"]
l2 = []
unchanged(l2)
# l2 == []
</code></pre></li>
<li><p>什么是列表和字典推导(list and dict comprehensions)?你能给个例子吗?</p>
<p>列表/字典推导是一种语法糖(syntax sugar),用来简化列表和字典的生成。根据第三版的”Learning Python”,列表推导的执行速度快于通常的循环,但并不确保以后的 Python 版本也是这个结果。</p>
<pre><code># simple iteration
a = []
for x in range(10):
a.append(x*2)
# a == [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# list comprehension
a = [x*2 for x in range(10)]
# dict comprehension
a = {x: x*2 for x in range(10)}
# a == {0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18
# set comprehension
a = {x**2 for x in range(10) if x % 2 == 0}
# a == set([0, 16, 4, 64, 36])
</code></pre>
<p><strong>列表推导是典型的 Pythonic 的代码书写方式。</strong></p></li>
<li><p>什么是 PEP 8?</p>
<p>PEP 8 定义的是 Python 代码规范,告诉你如何书写可读性强,更好维护的代码。详细内容请参考<a href="http://www.python.org/dev/peps/pep-0008/">PEP 8 官方文档</a>。Sublime Text编辑工具带有 PEP 8 格式检测插件,所存盘的文件都应当符合 PEP 8 的规范。</p></li>
<li><p>你使用虚拟环境(virtual environment)吗?</p>
<p>很多 Python 程序员认为,包括我自己也是这样的观点,<a href="https://pypi.python.org/pypi/virtualenv">virtual environment</a>是一个非常有用的工具,用来孤立你的开发和运行环境,特别是当需要同时开发多个项目,基于不同的 Python 版本以及运行库的时候。每当新建一个项目,或者clone一个已存在项目的时候,我都会按照下面的步骤建立和使用虚拟环境:</p>
<pre><code># create virtual env
virtualenv --no-site-packages --python=python3.2 ./venv
# activate virtual env
source ./venv/bin/activate
# install requirements
pip install -r requirements.txt
#.....
# update requirements
pip freeze > requirements.txt
</code></pre></li>
<li><p>如何计算列表里所有元素的和?如何计算列表里所有元素的乘积?</p>
<p>这个问题相当简单,但需要记住一点,你需要用 Pythonic 的方式来解答这个问题:</p>
<pre><code># 计算列表内所有元素的和, 包括基本loop方式,sum函数方式,以及使用reduce函数
# the basic way
s = 0
for x in range(10):
s += x
# the right way
s = sum(range(10))
# the other way
from operator import add
s = reduce(add, range(10))
# 计算列表内所有元素的乘积
# the basic way
s = 1
for x in range(1, 10):
s = s * x
# the other way
from operator import mul
reduce(mul, range(1, 10))
</code></pre></li>
<li><p>你能列出列表(list)和元组(tuple)的区别吗?举例子说明用法的不同。</p>
<p>列表和元组是 Python 里最基本的两个数据类型:</p>
<ul>
<li>首先,列表对象是可变的(mutable),但元组不是;</li>
<li>其次,元组可被哈希(hashed),例如可以用作字典对象的键值(key);</li>
</ul>
<p>至于例子,地图上的地理坐标可以用二元组表示,而地图上的路径可以用坐标点列表来表示。</p></li>
<li><p>你知道<code>range</code>和<code>xrange</code>的区别吗?</p>
<p><code>range</code>函数返回的是一个列表对象,<code>xrange</code>返回的是一个<code>xrange</code>对象。他们的主要区别是:</p>
<ul>
<li>内存的占用不同。列表对象已经在内存中存在了,而<code>xrange</code>对象永远占
用同样的内存大小,无论需要生成的<code>range</code>有多大。</li>
<li><code>xrange</code>对象不能使用列表对象的切片函数,也就是说
<code>range(10)[3:5]</code>能工作,但是<code>xrange(10)[3:5]</code>就不工作了。</li>
</ul>
<p>类似的问题还有:<code>map</code>和<code>itertools.imap</code>的区别?<code>filter</code>和<code>itertools.ifilter</code>的区别?清楚这些区别,你就能知道怎样更有效地使用这些函数。</p></li>
<li><p>请说出一些 python2.x 与 python3.x 之间的区别。</p>
<p>如果你经常看网上的文章,你肯定能说出一些区别:</p>
<ul>
<li>python3.x 的字符串都是unicode;</li>
<li>python3.x 中<code>print</code>是函数,而不是语句;</li>
<li>python3.x 中使用<code>range</code>代替了<code>xrange</code>,删除了<code>xrange</code>函数;</li>
<li>python3.x 中全部类(class)都是新类型(new style);</li>
<li>python3.x 支持更简单的<code>unpack</code>方式,如<code>first, *middle, last = [0, 1, 2, 3, 4, 5, 6, 7]</code></li>
</ul>
<p>如果你一条区别也说不出来,至少说明你对 Python 的关注度不够。</p></li>
<li><p>什么是修饰器(Decorator)?你能说出它的用途吗?</p>
<p>修饰器(Decorator)也是一种非常 Pythonic 的方式,它可以让你非常方便地注入(inject)或者修改函数和类的代码。换句话说,修饰器允许你包装函数和类方法,在执行原始代码之前和之后执行其他的代码。修饰器语法能带来很多非常有意思的编码方式,例如:</p>
<ul>
<li><p>内存缓存</p>
<pre><code> def memoize(f):
memo = {} # 将结果缓存在memo字典对象中,key是参数,value是结果。
def helper(x):
if x not in memo:
memo[x] = f(x)
return memo[x]
return helper
# 修饰fib函数,任何fib函数的调用,将首先察看是否已经有缓存的结果
@memoize
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
print(fib(40)) # 102334155
</code></pre></li>
<li><p>参数检测</p>
<pre><code> def argument_test_natural_number(f):
def helper(x):
if type(x) == int and x > 0:
return f(x)
else:
raise Exception("Argument is not an integer")
return helper
@argument_test_natural_number
def faculty(n):
if n == 1:
return 1
else:
return n * faculty(n-1)
for i in range(1,10):
print(i, faculty(i))
# 1 1
# 2 2
# 3 6
# 4 24
# 5 120
# 6 720
# 7 5040
# 8 40320
# 9 362880
faculty(-1) # 使用非法的参数调用faculty函数,这将raise一个exception
# Exception: Argument is not an integer
</code></pre></li>
</ul>
</li>
<li><p> <code>with</code>语句及其用法?</p>
<p>简单地说,<code>with</code>语句允许你在进入和/或退出指定的代码块的时候,执行特定的代码。最常用的例子是使用<code>with</code>句打开文件。为了在你自己定义的对象上使用<code>with</code>语句,你必须定义<code>__enter__</code>和<code>__exit__</code>方法。</p>
<p>更多的信息你可以查看<a href="http://effbot.org/zone/python-with-statement.htm">理解 Python 的 with 语句</a>。</p></li>
</ol>
<hr />
<p>除了原文列举上述问题,下面知识点也是 Python 面试中很可能被问到的:</p>
<ul>
<li>Package/Module的定义,以及模块加载原则;</li>
<li>如何构建你自己的类型,如列表(list),字典(dict),迭代器(iterator);</li>
<li>生成器(generator)的概念以及使用方式;</li>
<li>built-in 类型和函数;</li>
<li>对象属性的操作原理,如<strong>dict</strong>,<strong>getattr</strong>,<strong>getattribute</strong>,描述
器(descriptor);</li>
<li>元类编程(metaclass)的概念,以及如何使用;</li>
<li>如何进行Package/Module的打包和分发;</li>
<li>什么是WSGI;</li>
<li>字符串的处理和正则表达式;</li>
<li>如何操作json和xml数据;</li>
</ul>
<p>另外,还必须尽可能地多了解 Python 语言最为强大的
<a href="http://docs.python.org/2/library/">库函数</a>。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[在Python中生成单体实例的方法]]></title>
<link href="http://xiaocong.github.io/blog/2013/06/04/creating-a-singleton-in-python/"/>
<updated>2013-06-04T10:53:00+08:00</updated>
<id>http://xiaocong.github.io/blog/2013/06/04/creating-a-singleton-in-python</id>
<content type="html"><![CDATA[<p>Python是很强力的编程语言,它即支持面向对象编程的特征,也支持很多函数式编程的特征,同时还是一门动态语言。由于Python语言特征的多样性,对于同一种设计需求,我们可以采用多种完全不同的方式进行实现。优秀的软件工程师总能在这些实现方式中,根据他们的优劣,选择出最适合的方式。</p>
<p>下面的内容源自<a href="http://stackoverflow.com/">StackOverflow</a>的一篇文章:<a href="http://stackoverflow.com/questions/6760685/creating-a-singleton-in-python">Creating a singleton in python</a>
。</p>
<blockquote><p>这个问题不是为了讨论单体实例是否是有必要的,或者是反面模式,也不是为了挑起任何宗教式的战争,而是为了讨论如何用更Pythonic的方式,最佳地实现单体实例模式。</p></blockquote>
<!--more-->
<h2>方法1:装饰器(Decorator)</h2>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">singleton</span><span class="p">(</span><span class="n">class_</span><span class="p">):</span>
</span><span class='line'> <span class="n">instances</span> <span class="o">=</span> <span class="p">{}</span>
</span><span class='line'> <span class="k">def</span> <span class="nf">getinstance</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span class='line'> <span class="k">if</span> <span class="n">class_</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">instances</span><span class="p">:</span>
</span><span class='line'> <span class="n">instances</span><span class="p">[</span><span class="n">class_</span><span class="p">]</span> <span class="o">=</span> <span class="n">class_</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span><span class='line'> <span class="k">return</span> <span class="n">instances</span><span class="p">[</span><span class="n">class_</span><span class="p">]</span>
</span><span class='line'> <span class="k">return</span> <span class="n">getinstance</span>
</span><span class='line'>
</span><span class='line'><span class="nd">@singleton</span>
</span><span class='line'><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">BaseClass</span><span class="p">):</span>
</span><span class='line'> <span class="k">pass</span>
</span><span class='line'>
</span><span class='line'><span class="n">c</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
<p><strong>优点</strong></p>
<ul>
<li>装饰器在通常情况下比其他任何方式都要直观。</li>
</ul>
<p><strong>缺点</strong></p>
<ul>
<li>任何通过调用<code>MyClass()</code>能获得真的单体实例,但是<code>MyClass</code>本身却被装饰成一个函数(function)了,也就是说不能使用任何类方法和与类相关的函数如<code>isinstance</code>,<code>issubclass</code>等。</li>
<li>还能从<code>MyClass</code>继承一个子类么?</li>
</ul>
<h2>方法2:基类继承</h2>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">Singleton</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
</span><span class='line'> <span class="n">_instances</span> <span class="o">=</span> <span class="p">{}</span>
</span><span class='line'> <span class="k">def</span> <span class="nf">__new__</span><span class="p">(</span><span class="n">class_</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span class='line'> <span class="k">if</span> <span class="n">class_</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">class_</span><span class="o">.</span><span class="n">_instances</span><span class="p">:</span>
</span><span class='line'> <span class="n">class_</span><span class="o">.</span><span class="n">_instances</span><span class="p">[</span><span class="n">class_</span><span class="p">]</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">Singleton</span><span class="p">,</span> <span class="n">class_</span><span class="p">)</span><span class="o">.</span><span class="n">__new__</span><span class="p">(</span><span class="n">class_</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span><span class='line'> <span class="k">return</span> <span class="n">class_</span><span class="o">.</span><span class="n">_instances</span><span class="p">[</span><span class="n">class_</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">Singleton</span><span class="p">,</span> <span class="n">BaseClass</span><span class="p">):</span> <span class="c"># 这里Singleton必须放在其他基类前面</span>
</span><span class='line'> <span class="k">pass</span>
</span><span class='line'>
</span><span class='line'><span class="n">c</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
<p><strong>优点</strong></p>
<ul>
<li><code>MyClass</code>是真的类(class)。</li>
</ul>
<p><strong>缺点</strong></p>
<ul>
<li>多继承…得小心使用!</li>
</ul>
<h2>方法3:元类(Metaclass)</h2>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">Singleton</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
</span><span class='line'> <span class="n">_instances</span> <span class="o">=</span> <span class="p">{}</span>
</span><span class='line'> <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span class='line'> <span class="k">if</span> <span class="n">cls</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cls</span><span class="o">.</span><span class="n">_instances</span><span class="p">:</span>
</span><span class='line'> <span class="n">cls</span><span class="o">.</span><span class="n">_instances</span><span class="p">[</span><span class="n">cls</span><span class="p">]</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">Singleton</span><span class="p">,</span> <span class="n">cls</span><span class="p">)</span><span class="o">.</span><span class="n">__call__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span><span class='line'> <span class="k">return</span> <span class="n">cls</span><span class="o">.</span><span class="n">_instances</span><span class="p">[</span><span class="n">cls</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">BaseClass</span><span class="p">):</span>
</span><span class='line'> <span class="n">__metaclass__</span> <span class="o">=</span> <span class="n">Singleton</span>
</span><span class='line'>
</span><span class='line'><span class="n">c</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
<p><strong>忧点</strong></p>
<ul>
<li><code>MyClass</code>是真的类(class)</li>
<li>魔术般地覆盖了继承的案例。</li>
<li>有目的地使用<code>__metaclass__</code>,让阅读者明确地知道这个目的。</li>
</ul>
<p><strong>缺点</strong></p>
<ul>
<li>如果有的话,就是很多程序员不熟悉元类(MetaClass)。</li>
</ul>
<h2>方法4:装饰器(Decorator)返回相同名称的类(Class)</h2>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">singleton</span><span class="p">(</span><span class="n">class_</span><span class="p">):</span>
</span><span class='line'> <span class="k">class</span> <span class="nc">class_w</span><span class="p">(</span><span class="n">class_</span><span class="p">):</span>
</span><span class='line'> <span class="n">_instance</span> <span class="o">=</span> <span class="bp">None</span>
</span><span class='line'> <span class="k">def</span> <span class="nf">__new__</span><span class="p">(</span><span class="n">class_</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span class='line'> <span class="k">if</span> <span class="n">class_w</span><span class="o">.</span><span class="n">_instance</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
</span><span class='line'> <span class="n">class_w</span><span class="o">.</span><span class="n">_instance</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">class_w</span><span class="p">,</span> <span class="n">class_</span><span class="p">)</span><span class="o">.</span><span class="n">__new__</span><span class="p">(</span><span class="n">class_</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span><span class='line'> <span class="n">class_w</span><span class="o">.</span><span class="n">_instance</span><span class="o">.</span><span class="n">_sealed</span> <span class="o">=</span> <span class="bp">False</span>
</span><span class='line'> <span class="k">return</span> <span class="n">class_w</span><span class="o">.</span><span class="n">_instance</span>
</span><span class='line'> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span class='line'> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_sealed</span><span class="p">:</span>
</span><span class='line'> <span class="k">return</span>
</span><span class='line'> <span class="nb">super</span><span class="p">(</span><span class="n">class_w</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span><span class='line'> <span class="bp">self</span><span class="o">.</span><span class="n">_sealed</span> <span class="o">=</span> <span class="bp">True</span>
</span><span class='line'> <span class="n">class_w</span><span class="o">.</span><span class="n">__name__</span> <span class="o">=</span> <span class="n">class_</span><span class="o">.</span><span class="n">__name__</span>
</span><span class='line'> <span class="k">return</span> <span class="n">class_w</span>
</span><span class='line'>
</span><span class='line'><span class="nd">@singleton</span>
</span><span class='line'><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">BaseClass</span><span class="p">):</span>
</span><span class='line'> <span class="k">pass</span>
</span><span class='line'>
</span><span class='line'><span class="n">c</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
<p><strong>优点</strong></p>
<ul>
<li><code>MyClass</code>是真的类(class)</li>
<li>魔术般地覆盖了继承的案例。</li>
</ul>
<p><strong>缺点</strong></p>
<ul>
<li>生成一个新类有额外的开销没?每定义一个类,实际上生成了两个类来实现单体实例。通常情况下不是问题,但扩展的时候可能有麻烦。</li>
<li>对于<code>_sealed</code>属性有什么观点了?</li>
<li><code>MyClass</code>是另外一个具有同样名称的<code>MyClass</code>类的子类,是否有点怪诞?这就意味着<strong>你不能在子类的方法中通过<code>super</code>方法调用基类的相同的方法</strong>,因为这是递归调用。</li>
</ul>
<hr />
<p>上面列出了四种不同的方式实现了单体实例,分别用到了装饰器(Decorator),元类(MetaClass),和多继承(Multiple Inheritance)等语言特征(实际上还有很多其他实现方式)。如果程序中用不到类(class)相关的函数和方法,第一种方法就已经足够了,否则我们只能考虑方法2、3或者4。</p>
<p><strong>还有没有更简单的方法了???</strong></p>
<p>抛开固有的思维模式,<strong>keep it simple!</strong></p>
<p>在<a href="http://stackoverflow.com/a/6760726/1070484">stackoverflow</a>上投票最
多的答案是:</p>
<blockquote><p>Modules are imported only once, everything else is overthinking. Don’t use singletons and try not to use globals.</p></blockquote>
<p>用代码解释就是:</p>
<ul>
<li>定义一个模块,如<code>mymodule</code></li>
</ul>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="c"># mymodule.py</span>
</span><span class='line'><span class="k">class</span> <span class="nc">Foo</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
</span><span class='line'> <span class="k">def</span> <span class="nf">somemethod</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'> <span class="k">pass</span>
</span><span class='line'>
</span><span class='line'><span class="n">some_global_variable</span> <span class="o">=</span> <span class="n">Foo</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
<ul>
<li>在其他模块中引入该实例:</li>
</ul>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">mymodule</span> <span class="kn">import</span> <span class="n">some_global_variable</span> <span class="k">as</span> <span class="n">foo</span>
</span><span class='line'>
</span><span class='line'><span class="n">foo</span><span class="o">.</span><span class="n">somemethod</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[在 Markdown 中嵌入 UML 文档]]></title>
<link href="http://xiaocong.github.io/blog/2013/04/22/writing-development-documentation-with-markdown/"/>
<updated>2013-04-22T13:23:00+08:00</updated>
<id>http://xiaocong.github.io/blog/2013/04/22/writing-development-documentation-with-markdown</id>
<content type="html"><![CDATA[<p><a href="http://daringfireball.net/projects/markdown/" title="Markdown">Markdown</a>是网络书写语言,特别适合程序员书写文档:</p>
<ul>
<li>全文本格式,方便进行<code>diff</code>,<code>patch</code>和版本的管理;</li>
<li>格式直观,简单易学,便于书写和阅读;</li>
<li>兼容 HTML,能方便地转换为 pdf,doc等格式;</li>
<li>支持 Linux,Windows,Mac;</li>
<li>支持内嵌代码和语法高亮;</li>
</ul>
<p>估计只是方便版本管理,就能吸引很多程序员的兴趣,特别是需要团队一起参与书写文档的时候。感兴趣的可以参考官方网站,或者以前写的一份<a href="http://xiaocong.github.io/slides/writing-documentation-with-markdown/">使用 Markdown 的 slides</a>。</p>
<p>但是毕竟<a href="http://daringfireball.net/projects/markdown/" title="Markdown">Markdown</a>只是书写语言,不是程序设计语言,如果我们需要嵌入 UML 的时候,不可避免地需要其他专业软件的支持。这里介绍几种利用网络服务,可以直接在<a href="http://daringfireball.net/projects/markdown/" title="Markdown">Markdown</a>文档中嵌入的 UML 建模图:</p>
<!--more-->
<hr />
<h2>用例图</h2>
<ul>
<li><p>角色(Actor)</p>
<p> 使用<code>[角色名]</code>表示角色。</p>
<pre><code> <img src="http://yuml.me/diagram/scruffy/usecase/[Customer]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/scruffy/usecase/[Customer]" ></p></li>
<li><p>用例(Use Case)</p>
<p> 使用<code>(用例名)</code>表示用例,<code>-</code>表示角色和用例之间的关联。</p>
<pre><code> <img src="http://yuml.me/diagram/scruffy/usecase/[Customer]-(Login),[Customer]-(Logout)" >
</code></pre>
<p> <img src="http://yuml.me/diagram/scruffy/usecase/[Customer]-(Login),[Customer]-(Logout)" ></p></li>
<li><p>备注(Notes)</p>
<p> 如果用例名以<code>note:</code>开头,表明那是一个备注,可以用<code>{bg:颜色名}</code>定义备注的背景色。</p>
<pre><code> <img src="http://yuml.me/diagram/scruffy/usecase/[Customer]-(Login), [Customer]-(note: Cust can be registered or not{bg:beige})" >
</code></pre>
<p> <img src="http://yuml.me/diagram/scruffy/usecase/[Customer]-(Login), [Customer]-(note: Cust can be registered or not{bg:beige})" ></p></li>
<li><p>角色继承(Actor Inheritance)</p>
<p> 使用符号<code>^</code>表示角色之间的继承关系。</p>
<pre><code> <img src="http://yuml.me/diagram/scruffy/usecase/[Cms Admin]^[User], [Customer]^[User], [Agent]^[User]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/scruffy/usecase/[Cms Admin]^[User], [Customer]^[User], [Agent]^[User]" ></p></li>
<li><p>扩展和包含(Extends and Includes)</p>
<p> 使用<code>></code>表示用例之间的包含关系,<code><</code>表示用例的扩展。</p>
<pre><code> <img src="http://yuml.me/diagram/scruffy/usecase/(Login)<(Register),(Login)<(Request Password Reminder),(Register)>(Confirm Registration)" >
</code></pre>
<p> <img src="http://yuml.me/diagram/scruffy/usecase/(Login)%3C(Register),(Login)%3C(Request%20Password%20Reminder),(Register)%3E(Confirm%20Registration)" ></p></li>
<li><p>完整示例</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/usecase/(note: figure 1.2{bg:beige}), [User]-(Login),[Site Maintainer]-(Add User),(Add User)<(Add Company),[Site Maintainer]-(Upload Docs),(Upload Docs)<(Manage Folders),[User]-(Upload Docs), [User]-(Full Text Search Docs), (Full Text Search Docs)>(Preview Doc),(Full Text Search Docs)>(Download Docs), [User]-(Browse Docs), (Browse Docs)>(Preview Doc), (Download Docs), [Site Maintainer]-(Post New Event To The Web Site), [User]-(View Events)" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/usecase/(note:%20figure%201.2%7Bbg:beige%7D),%20[User]-(Login),[Site%20Maintainer]-(Add%20User),(Add%20User)%3C(Add%20Company),[Site%20Maintainer]-(Upload%20Docs),(Upload%20Docs)%3C(Manage%20Folders),[User]-(Upload%20Docs),%20[User]-(Full%20Text%20Search%20Docs),%20(Full%20Text%20Search%20Docs)%3E(Preview%20Doc),(Full%20Text%20Search%20Docs)%3E(Download%20Docs),%20[User]-(Browse%20Docs),%20(Browse%20Docs)%3E(Preview%20Doc),%20(Download%20Docs),%20[Site%20Maintainer]-(Post%20New%20Event%20To%20The%20Web%20Site),%20[User]-(View%20Events)" ></p></li>
</ul>
<p><a href="http://yuml.me/">YUML</a>支持3种图示风格,分别是:</p>
<ul>
<li>plain</li>
<li>scruffy</li>
<li>boring</li>
</ul>
<p>你可以对比下列图示的不同风格:</p>
<p><img src="http://yuml.me/diagram/plain/usecase/[Customer]-(Login),[Customer]-(Logout),(login)<(Register)" >
<img src="http://yuml.me/diagram/scruffy/usecase/[Customer]-(Login),[Customer]-(Logout),(login)<(Register)" >
<img src="http://yuml.me/diagram/boring/usecase/[Customer]-(Login),[Customer]-(Logout),(login)<(Register)" ></p>
<h2>活动图</h2>
<ul>
<li><p>动作(Action)</p>
<p> 用<code>(状态名)</code>表示一个状态,其中<code>(start)</code>和<code>(end)</code>分别表示开始状态和结束状态,箭头<code>-></code>表示状态的转换。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/activity/(start)->(Boil Kettle)->(end)" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/activity/(start)-%3E(Boil%20Kettle)-%3E(end)" ></p></li>
<li><p>判断和限制(Decisions and Constraints)</p>
<p> 使用<code><判断名></code>表示一个条件判断,其后跟<code>[条件]-></code>表示满足条件后状态的转换;用不同的<code>判断名</code>来标识不同的判定位置。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/activity/(start)-><a>[kettle empty]->(Fill Kettle)->(Boil Kettle),<a>[kettle full]->(Boil Kettle)->(end)" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/activity/(start)-%3E%3Ca%3E[kettle%20empty]-%3E(Fill%20Kettle)-%3E(Boil%20Kettle),%3Ca%3E[kettle%20full]-%3E(Boil%20Kettle)-%3E(end)" ></p></li>
<li><p>分支合并(Fork/Join)</p>
<p> 使用<code>||</code>表示分支或者合并点。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/activity/(start)-><a>[kettle empty]->(Fill Kettle)->|b|,<a>[kettle full]->|b|->(Boil Kettle)->|c|,|b|->(Add Tea Bag)->(Add Milk)->|c|->(Pour Water)->(end),(Pour Water)->(end)" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/activity/(start)-%3E%3Ca%3E[kettle%20empty]-%3E(Fill%20Kettle)-%3E%7Cb%7C,%3Ca%3E[kettle%20full]-%3E%7Cb%7C-%3E(Boil%20Kettle)-%3E%7Cc%7C,%7Cb%7C-%3E(Add%20Tea%20Bag)-%3E(Add%20Milk)-%3E%7Cc%7C-%3E(Pour%20Water)-%3E(end),(Pour%20Water)-%3E(end)" ></p></li>
<li><p>对象(Objects)</p>
<p> 符号<code>[]</code>表示一个对象。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/activity/(start)->[Water]->(Fill Kettle)->(end)" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/activity/(start)-%3E[Water]-%3E(Fill%20Kettle)-%3E(end)" ></p></li>
<li><p>连接器名称(Connector Name)</p>
<p> 在<code>-></code>中加入名称,<code>-名称></code>表示命名连接器。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/activity/(start)-fill>(Fill Kettle)->(end)" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/activity/(start)-fill%3E(Fill%20Kettle)-%3E(end)" ></p></li>
</ul>
<h2>类图</h2>
<ul>
<li><p>关联(Association)</p>
<p> 类名用<code>[]</code>表示,<code>-></code>表示定向关联,<code>-</code>表明关联。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[Customer]->[Billing Address]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[Customer]-%3E[Billing%20Address]" ></p></li>
<li><p>基数(Cardinality)</p>
<p> <code>基数-基数></code>表明关联的基数,其中基数可以为<code>0</code>,<code>1</code>,<code>0..*</code>,<code>*</code>等任意定义的值。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[Customer]1-0..*[Address]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[Customer]1-0..*[Address]" ></p></li>
<li><p>定向关联(Directional Association)</p>
<p> 定向关联<code>-></code>可以定义名称:<code>-名称></code>。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[Order]-billing >[Address], [Order]-shipping >[Address]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[Order]-billing%20%3E[Address],%20[Order]-shipping%20%3E[Address]" ></p></li>
<li><p>颜色和UTF8字符(Splash of Colour And UTF-8)</p>
<p> 类图可以用<code>{bg:颜色名}</code>定义显示的背景颜色。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[❝Customer❞{bg:orange}]❶- ☂>[Order{bg:green}]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[%E2%9D%9DCustomer%E2%9D%9E%7Bbg:orange%7D]%E2%9D%B6-%20%E2%98%82%3E[Order%7Bbg:green%7D]" ></p></li>
<li><p>聚合(Aggregation)</p>
<p> 聚合表示比关联更强的关联关系,使用<code><>-></code>或者<code>+-></code>来表示。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[Company]<>-1>[Location], [Location]+->[Point]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[Company]%3C%3E-1%3E[Location],%20[Location]+-%3E[Point]" ></p></li>
<li><p>组成(Composition)</p>
<p> 组成表示比聚合更强的关联关系,使用<code>++-></code>来表示。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[Company]++-1>[Location]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[Company]++-1%3E[Location]" ></p></li>
<li><p>备注(Notes)</p>
<p> 使用<code>[note:注解内容]</code>表示备注,同样备注可以自定义颜色<code>{bg:颜色名}</code>。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[Customer]<>1->*[Order], [Customer]-[note: Aggregate Root{bg:cornsilk}]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[Customer]%3C%3E1-%3E*[Order],%20[Customer]-[note:%20Aggregate%20Root%7Bbg:cornsilk%7D]" ></p></li>
<li><p>继承(Inheritance)</p>
<p> 使用<code>^-</code>表示类的继承,右边的类是子类。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[Wages]^-[Salaried], [Wages]^-[Contractor]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[Wages]%5E-[Salaried],%20[Wages]%5E-[Contractor]" ></p></li>
<li><p>接口继承(Interface Inheritance)</p>
<p> 接口继承用<code>^-.-</code>来表示。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[<<ITask>>]^-.-[NightlyBillingTask]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[%3C%3CITask%3E%3E]%5E-.-[NightlyBillingTask]" ></p></li>
<li><p>依赖(Dependencies)</p>
<p> 类的依赖用<code>-.-></code>来表示,依赖是最弱的关联关系,一般用来表示类方法的参数或者实现用到了依赖类。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[HttpContext]uses -.->[Response]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[HttpContext]uses%20-.-%3E[Response]" ></p></li>
<li><p>接口(Interface)</p>
<p> 和类名相比,接口的名称一般包含在<code><<>></code>中。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[<<IDisposable>>;Session]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[%3C%3CIDisposable%3E%3E;Session]" ></p></li>
<li><p>类定义(Class with Details)</p>
<p> 可以在类符号<code>[]</code>中定义类的所有成员。使用<code>|</code>表示类名与类成员变量和成员函数的分割符,不同的成员之间用<code>;</code>隔开,使用<code>+</code>,<code>-</code>分别表示公开和私有成员。</p>
<pre><code> <img src="http://yuml.me/diagram/nofunky/class/[User|+Forename+;Surname;+HashedPassword;-Salt|+Login();+Logout()]" >
</code></pre>
<p> <img src="http://yuml.me/diagram/nofunky/class/[User%7C+Forename+;Surname;+HashedPassword;-Salt%7C+Login();+Logout()]" ></p></li>