-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
1087 lines (618 loc) · 37.8 KB
/
index.html
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
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>ZhouQi's Blog</title>
<meta name="author" content="周琪(zhouqi)">
<meta name="description" content="Jan 16th, 2014 Python, interview Fibonacci in Python 这是一道面试的题目,实际很简单,但,我没很好答上来。因为不够pythonic。 我的实现 fib_list = [1, 1]
def _f(): global fib_list …">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/atom.xml" rel="alternate" title="ZhouQi's Blog" type="application/atom+xml">
<link rel="canonical" href="http://bitwolaiye.github.io/">
<link href="/favicon.png" rel="shortcut icon">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
<link href="/stylesheets/font-awesome.min.css" media="screen, projection" rel="stylesheet" type="text/css">
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400italic,400,700' rel='stylesheet' type='text/css'>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<!--Fonts from Google"s Web font directory at http://google.com/webfonts -->
</head>
<body>
<div class="container">
<div class="left-col">
<div class="intrude-less">
<header id="header" class="inner"><div class="profilepic">
<script src="/javascripts/md5.js"></script>
<script type="text/javascript">
$(function(){
$('.profilepic').append("<img src='http://www.gravatar.com/avatar/" + MD5("[email protected]") + "?s=160' alt='Profile Picture' style='width: 160px;' />");
});
</script>
</div>
<hgroup>
<h1><a href="/">ZhouQi's Blog</a></h1>
<h2>A blogging framework for hackers.</h2>
</hgroup>
<nav id="main-nav"><ul class="main-navigation">
<li><a href="/">Blog</a></li>
<li><a href="/blog/archives">Archives</a></li>
</ul>
</nav>
<nav id="sub-nav">
<div class="social">
<a class="email" href="mailto:[email protected]" title="Email">Email</a>
<a class="github" href="https://github.com/bitwolaiye" title="GitHub">GitHub</a>
<a class="rss" href="/atom.xml" title="RSS">RSS</a>
</div>
</nav>
</header>
</div>
</div>
<div class="mid-col">
<div class="mid-col-container">
<div id="content" class="inner">
<div itemscope itemtype="http://schema.org/Blog">
<article class="post" itemprop="blogPost" itemscope itemtype="http://schema.org/BlogPosting">
<div class="meta">
<div class="date">
<time datetime="2014-01-16T10:02:20+08:00" data-updated="true" itemprop="datePublished">Jan 16<span>th</span>, 2014</time></div>
<div class="tags">
<a class='category' href='/blog/categories/python/'>Python</a>, <a class='category' href='/blog/categories/interview/'>interview</a>
</div>
</div>
<h1 class="title" itemprop="name"><a href="/blog/2014/01/16/fibonacci-in-python/" itemprop="url">Fibonacci in Python</a></h1>
<div class="entry-content" itemprop="articleBody">
<p>这是一道面试的题目,实际很简单,但,我没很好答上来。因为不够pythonic。</p>
<p>我的实现</p>
<pre><code>fib_list = [1, 1]
def _f():
global fib_list
fib_list.append(sum(fib_list[-2:]))
def fib(index):
if index < 0:
return -1
global fib_list
if len(fib_list) < index:
for i in xrange(index - len(fib_list)):
_f()
return fib_list[index - 1]
</code></pre>
<p>当时我还写了另一个,但回来发现是错的。</p>
<p>搜了下,有这2个文章有更好的解法</p>
<p><a href="http://www.zacharyfox.com/blog/fibonacci-project/fibonacci-in-python">Fibonacci in Python</a></p>
<p><del><a href="http://www.cr173.com/html/6631_1.html">用Python实现Fibonacci函数</a></del></p>
<p>后一篇基本可以不看,就属于卖萌型的。回字有几种写法实际上只是程序员卖弄的技巧。</p>
<pre><code>def fibonacci(n):
a,b = 0,1
for i in range(0,n):
a,b, = b,a+b
return a
</code></pre>
<p>这个基本就是比较简洁的了。</p>
<p>还有一种Generator的实现方式</p>
<pre><code>def fib():
a, b = 0, 1
while 1:
yield a
a, b = b, a + b
a = fib()
a.next()
for i in range(10):
print a.next(),
</code></pre>
<p>但我得辩解下,对于非科班的程序员,在工作中我很少需要关注该数列的实现方式,往往是根据实际的业务现想。像背诵一样的默写出这个实现实际上没有太大意义。</p>
<p>不过还没完,我搜到了<a href="http://en.literateprograms.org/Category:Fibonacci_numbers">http://en.literateprograms.org/Category:Fibonacci_numbers</a></p>
<p>这个对该问题还有更加深入的解释。包括如何利用数学上的知识更快的算出结果。</p>
</div>
</article>
<article class="post" itemprop="blogPost" itemscope itemtype="http://schema.org/BlogPosting">
<div class="meta">
<div class="date">
<time datetime="2014-01-16T09:38:10+08:00" data-updated="true" itemprop="datePublished">Jan 16<span>th</span>, 2014</time></div>
<div class="tags">
<a class='category' href='/blog/categories/python/'>Python</a>
</div>
</div>
<h1 class="title" itemprop="name"><a href="/blog/2014/01/16/prepare-python-engineer-interview/" itemprop="url">准备Python工程师面试</a></h1>
<div class="entry-content" itemprop="articleBody">
<p>之前在招聘网站放过简历,于是前2天有面试电话打来,是一家业内号称卖“理念”的公司,也的确还算有名气的公司,自称大公司中的小公司。职位是Python工程师。心想去去也好,看看自己到底是个什么水平,呆一家公司9年时间,都不知道外面的世界是什么样的了,偶尔会狂妄自大,偶尔会妄自菲薄。</p>
<p>比如说去这家公司面试心里就很紧张,Python实际只用了2年时间,期间一直仅仅忙于实现功能即可,对很多细节都是一知半解,程序能通就Ok。所以我还挺认真的开始找找资料,复习下。<del>(当然还有个原因对方说有笔试,囧。心里很担心万一全不会多丢人啊!!)</del></p>
<p>这个总结是去之前写的,把它发出来的同时实际已经去过了,结果面试结果的感觉是不咋地,但也有好处,就是达到了认清自己、找到缺点的目的。ok,这块回头再写。</p>
<h3>pyc pyo pyd</h3>
<p><a href="http://www.cnblogs.com/dkblog/archive/2009/04/16/1980757.html">http://www.cnblogs.com/dkblog/archive/2009/04/16/1980757.html</a></p>
<h3>什么是pyc文件</h3>
<p>pyc是一种二进制文件,是由py文件经过编译后,生成的文件,是一种byte code,py文件变成pyc文件后,加载的速度有所提高,而且pyc是一种跨平台的字节码,是由python的虚拟机来执行的,这个是类似于JAVA或者.NET的虚拟机的概念。pyc的内容,是跟python的版本相关的,不同版本编译后的pyc文件是不同的,2.5编译的pyc文件,2.4版本的 python是无法执行的。</p>
<h3>什么是pyo文件</h3>
<p>pyo是优化编译后的程序 python -O 源文件即可将源程序编译为pyo文件</p>
<h3>什么是pyd文件</h3>
<p>pyd是python的动态链接库。</p>
<h3>为什么需要pyc文件</h3>
<p>这个需求太明显了,因为py文件是可以直接看到源码的,如果你是开发商业软件的话,不可能把源码也泄漏出去吧?所以就需要编译为pyc后,再发布出去。当然,pyc文件也是可以反编译的,不同版本编译后的pyc文件是不同的,根据python源码中提供的opcode,可以根据pyc文件反编译出 py文件源码,网上可以找到一个反编译python2.3版本的pyc文件的工具,不过该工具从python2.4开始就要收费了,如果需要反编译出新版本的pyc文件的话,就需要自己动手了(俺暂时还没这能力^—^),不过你可以自己修改python的源代码中的opcode文件,重新编译 python,从而防止不法分子的破解。</p>
<h3>py文件在运行时会产生pyc文件,用于缓存编译后代码 不完全正确 ?? why??</h3>
<h2>zen of python</h2>
<p>The Zen of Python, by Tim Peters</p>
<ul>
<li>Beautiful is better than ugly.</li>
<li>Explicit is better than implicit.</li>
<li>Simple is better than complex.</li>
<li>Complex is better than complicated.</li>
<li>Flat is better than nested.</li>
<li>Sparse is better than dense.</li>
<li>Readability counts.</li>
<li>Special cases aren’t special enough to break the rules.</li>
<li>Although practicality beats purity.</li>
<li>Errors should never pass silently.</li>
<li>Unless explicitly silenced.</li>
<li>In the face of ambiguity, refuse the temptation to guess.</li>
<li>There should be one— and preferably only one —obvious way to do it.</li>
<li>Although that way may not be obvious at first unless you’re Dutch.</li>
<li>Now is better than never.</li>
<li>Although never is often better than <em>right</em> now.</li>
<li>If the implementation is hard to explain, it’s a bad idea.</li>
<li>If the implementation is easy to explain, it may be a good idea.</li>
<li>Namespaces are one honking great idea — let’s do more of those!</li>
</ul>
<p>翻译</p>
<ul>
<li>美比丑好</li>
<li>直言不讳比心照不宣好</li>
<li>简单比复杂好</li>
<li>复杂比难以理解好</li>
<li>平面的比嵌套的好</li>
<li>错落有致比密密匝匝的好</li>
<li>可读性很重要</li>
<li>虽然实用比纯粹更重要 但特殊情况不能特殊到打破规律</li>
<li>永远别让错误悄悄地溜走 除非是你故意的</li>
<li>碰到模棱两可的地方,绝对不要去作猜测</li>
<li>什么事情都应该有一个,而且最好只有一个显而易见的解决办法</li>
<li>虽然刚开始的时候,这个办法可能不是那么的显而易见,但谁叫你不是荷兰人</li>
<li>有些事情不理不睬可能会比过一会解决要好</li>
<li>但最好是现在就解决</li>
<li>如果一个想法实现起来很困难,那它本身就不是一个好想法</li>
<li>如果一个想法实现起来很容易,那它或许就是一个好想法</li>
<li>命名空间是一个很了不起的想法,让我们多多使用吧</li>
</ul>
<h2>排序</h2>
<pre><code>str_list = ['a', 'b', 'c']
str_list.sort(key=lambda x:x.lower(),reverse=True)
</code></pre>
<h2>随机</h2>
<pre><code>import random
random.random()
random.sample(range(10), 2)
l = range(10)
random.shuffle(l)
</code></pre>
<h2>文件</h2>
<pre><code>with open('1.txt', 'w') as f:
f.write('abc')
with open('1.txt', 'r') as f:
for s in f:
print s
import os
os.listdir('.')
import shutil
shutil.copyfile('1.txt', '2.txt')
os.remove('2.txt')
</code></pre>
<h2>.items() .iteritems()</h2>
<p>一个生成全部,一个是迭代器</p>
<h2>常用类型常用方法</h2>
<pre><code>dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
dir(tuple)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
dir(dict)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']
dir(set)
['__and__', '__class__', '__cmp__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']
dir(str)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
</code></pre>
<h3>list</h3>
<p>list可以作为栈</p>
<p>list可以作为队列</p>
<p>list到list的映射。??不明白</p>
<p>any和all在list中的使用。</p>
<pre><code>l = range(10)
all(n<10 for n in l)
any(n==0 for n in l)
</code></pre>
<p>list与for的结合,相当于高级语言中的foreach功能。</p>
<p>对list的enumerate与for的结合,相当于高级语言中的for功能。</p>
<p>list的嵌套使用,相当于多维数组。</p>
<p>del相当于list本身的remove,都可以用来删除list中的元素。</p>
<pre><code>l = range(10)
del l[9]
</code></pre>
<p>zip</p>
<h3>tuple</h3>
<p>tuple相当于是不可修改的list,所以同时也不具有list的很多修改的方法,例如append,insert,remove等;但是tuples仍然可以使用count,index等查找方法。</p>
<p>使用 t2 = (2,4,8)来定义tuple,也可以使用list来定义tuple如 l = [1,2,3] 和 t = tuple(l)</p>
<h3>set</h3>
<p>set的定义使用{}。</p>
<p>可以将list使用set显示的转化为set。</p>
<p>可以用in来判断指定元素是否存在于set中。</p>
<p>set于for结合使用,相当于foreach。</p>
<p>set可以进行|,&,^,-操作。</p>
<h3>dict</h3>
<p>dictionary使用{1 : ‘tom’, 2 : ‘bill’}来定义,也可以使用dict([(‘sape’, 4139), (‘guido’, 4127), (‘jack’, 4098)])来从list定义dictionary。</p>
<p>[]=来增加新的值。</p>
<p>del来删除指定的key和value。</p>
<p>in用来查找key是否存在。</p>
<h3>语法糖</h3>
<pre><code>isinstance([], list)
isinstance((), tuple)
isinstance({}, dict)
isinstance({1:2}, dict)
isinstance({1}, set)
</code></pre>
<h2>Pythonic</h2>
<p>只可意会不可言传!</p>
<p>或者 参见</p>
<pre><code>import this
</code></pre>
<h2>help</h2>
<p>参看方法参数</p>
<pre><code>help(''.index)
</code></pre>
<h2>lambda</h2>
<p>好处</p>
<p>匿名函数, 方便, 类函数式, 写回调方便</p>
<h3>filter</h3>
<p>filter(function, sequence):对sequence中的item依次执行function(item),将执行结果为True的item组成一个List/String/Tuple(取决于sequence的类型)返回:</p>
<h3>map</h3>
<p>map(function, sequence) :对sequence中的item依次执行function(item),见执行结果组成一个List返回:</p>
<h3>reduce</h3>
<p>reduce(function, sequence, starting_value):对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用,例如可以用来对List求和:</p>
<h2>range xrange</h2>
<p>一个列表 <del>一个迭代器</del> xrange</p>
<h2>yield</h2>
<p>???</p>
<h2>python支持多线程,能够单进程无缝发挥多路CPU的优势</h2>
<p>支持,不能够</p>
<p>为什么不能?并行计算?Python的线程实际上是使用单核在运行。</p>
<p><a href="https://wiki.python.org/moin/ParallelProcessing">https://wiki.python.org/moin/ParallelProcessing</a></p>
<blockquote><p>在大多数系统上,Python同时支持消息传递和基于线程的并发编程。尽管大多数程序员熟悉的往往是线程接口,但实际上Python线程受到的限制有很多。尽管最低限度是线程安全的,但Python解释器还是使用了内部的GIL(Global Interperter Lock,全局解释器锁定),在任意指定的时刻只能在一个处理器上运行。尽管GIL经常是Python社区中争论的热点,但在可以预见的将来它都不可能消失。</p></blockquote>
<p>号称来源于《python参考手册》但我没去证实。</p>
<h2>在python中,使用for从列表中删除元素是错误的做法,会导致漏删元素。正确的做法是使用python内置的filter函数</h2>
<br/>
<h2>题目 考虑Decorator 装饰器</h2>
<pre><code>def wrap_info (f):
b = {"b":10};
def inner_func (*p, **k):
print b['b'], p, k;
b['b'] += 1;
f(*p, **k);
return inner_func;
def info (s): print "func info: %s" % s;
if __name__ == "__main__":
f1 = wrap_info (info);
f1 ("a");
f2 = wrap_info (info);
f1 ("b");
f2 ("c");
</code></pre>
<p><a href="http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html">Python装饰器学习(九步入门)</a></p>
<h2>题目 纯卖弄!</h2>
<pre><code>a="a=%s%s%s;print a%%(chr(34),a,chr(34));";print a%(chr(34),a,chr(34));
</code></pre>
<h2>题目 单例模式</h2>
<pre><code>class singleton (object):
""" 单例模式的实现 """
def __new__ (cls, **kargs):
if '_instance' not in cls.__dict__:
cls._instance = object.__new__ (cls, **kargs);
return cls._instance;
</code></pre>
<h2>动态加载 反射等</h2>
<p><a href="http://www.cnblogs.com/huxi/archive/2011/01/02/1924317.html">Python自省(反射)指南</a></p>
<h3>访问元数据</h3>
<h3>使用inspect</h3>
<h2>unicode</h2>
<pre><code>s.decode('utf-8')
u.encode()
</code></pre>
<h2>传值?传引用?传值!</h2>
<p><a href="http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference/986145#986145">stackoverflow</a></p>
<p>简单来说,你在方法里重新对一个参数赋值可能不会改变。</p>
<p>建议是return出来然后改变</p>
<pre><code>class PassByReference:
def __init__(self):
self.variable = 'Original'
self.Change(self.variable)
print self.variable
def Change(self, var):
var = 'Changed'
p = PassByReference()
p.Change(p.variable)
print p.variable # Original
</code></pre>
<p>改为</p>
<pre><code>class PassByReference:
def __init__(self):
self.variable = 'Original'
self.Change()
print self.variable
def Change(self):
self.variable = 'Changed'
p = PassByReference()
p.Change()
print p.variable # Changed
</code></pre>
<p>或者</p>
<pre><code>class PassByReference:
def __init__(self):
self.variable = 'Original'
self.Change(p.variable)
print self.variable
def Change(self, var):
return 'Changed'
p = PassByReference()
p.variable = p.Change(p.variable)
print p.variable # Changed
</code></pre>
<p>甚至是变成一个数组传进去等等,但真不是个好办法了。太丑!</p>
<h2>进阶链接</h2>
<p><a href="http://ilian.i-n-i.org/python-interview-question-and-answers/">Python Interview Question and Answers</a></p>
<h2>Python的内存是使用的heap?</h2>
<p><a href="http://docs.python.org/2/c-api/memory.html">http://docs.python.org/2/c-api/memory.html</a></p>
<p><a href="http://www.ruanyifeng.com/blog/2013/11/stack.html">阮一峰对堆和栈的解释</a></p>
<h2>virtualenv</h2>
<pre><code>source activate
deactivate
pip freeze > filename
pip install -r filename
</code></pre>
</div>
</article>
<article class="post" itemprop="blogPost" itemscope itemtype="http://schema.org/BlogPosting">
<div class="meta">
<div class="date">
<time datetime="2013-12-12T22:15:26+08:00" data-updated="true" itemprop="datePublished">Dec 12<span>th</span>, 2013</time></div>
<div class="tags">
</div>
</div>
<h1 class="title" itemprop="name"><a href="/blog/2013/12/12/system-migration/" itemprop="url">系统迁移</a></h1>
<div class="entry-content" itemprop="articleBody">
<p>因为各种原因,准备将原来的跑db+api的服务器与存放图片的服务器合并,同时由于db+api的服务器的系统版本老、配置低、硬盘小,所以只能采用往图片服务器迁移的方案。那么迁移db+api的话就有不少风险,因为不是简单的把文件挪过去那么简单了。我觉得难点应该是db的数据迁移和api的环境迁移。db的方面有大拿解决,我就得自己准备api的环境迁移。我心里没大把握,所以提前抽点时间做点功课,减少出现问题的几率。</p>
<p>我做了以下检查</p>
<ul>
<li>系统版本</li>
<li>系统软件包</li>
<li>python版本</li>
<li>pip下已安装的python包</li>
<li>nginx配置</li>
<li>定时任务cron</li>
<li>其他服务</li>
</ul>
<p>我感觉检查pip下已安装包是个重要点。</p>
<p>命令:</p>
<pre><code>$ pip freeze
</code></pre>
</div>
</article>
<article class="post" itemprop="blogPost" itemscope itemtype="http://schema.org/BlogPosting">
<div class="meta">
<div class="date">
<time datetime="2013-12-04T00:10:30+08:00" data-updated="true" itemprop="datePublished">Dec 4<span>th</span>, 2013</time></div>
<div class="tags">
</div>
</div>
<h1 class="title" itemprop="name"><a href="/blog/2013/12/04/about-csrf/" itemprop="url">关于CSRF</a></h1>
<div class="entry-content" itemprop="articleBody">
<h2>一、什么是csrf</h2>
<br/>
<p><a href="http://baike.baidu.com/view/1609487.htm">CSRF from 百度百科</a></p>
<p>CSRF(Cross-site request forgery跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。</p>
<p>其实是2个原因导致了风险的出现:</p>
<ol>
<li>为了提高用户的体验,很多网站会在用户的本地存放用户的标示,一般是在浏览器的cookie里存放。这样用户第一次登录过网站后就不用再次登录,甚至在关机后再次打开就可以与后台发起交易,不需要再次验证身份。有人问,如果我的电脑不给人使用就我自己使用,那么是不是在享受方便之余并不损失安全性呢?那么请看2.</li>
<li>我们可以称第一步的网站为网站A。那么如果你访问了恶意网站B,而网站B里插入了一段直接post到网站A的form(或带有了一个直接请求网站A的url),此时你如果不小心点到了,那么浏览器会去执行表单,同时如果浏览器执行表单的时候会带上你之前留下的cookie,于是灾难发生了。还有人说,如果我少去上xx网站是否就安全了,其实还不是,因为比如以前的论坛等网站可能可以贴js代码,或者带url请求的图片等,那个时候你可能还是可能中招。</li>
</ol>
<p>作为程序员,我们怎么让自己的应用免受csrf攻击呢?</p>
<ol>
<li>去掉cookie自动登录,不让用户方便!ok,这个会被骂的,pass。</li>
<li>对请求增加一个随机数,这个随机数是第三方不能轻易伪造的。<a href="http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html">浅谈CSRF攻击方式</a> 在这里面提供了3种方式,都是个思路。其实我认为靠谱的还是第一种,django也是这种方式。下面来看django来如何抵御csrf攻击。</li>
</ol>
<h2>二、django怎么抵御csrf攻击</h2>
<br/>
<p><a href="https://docs.djangoproject.com/en/dev/ref/contrib/csrf">原文</a></p>
<h3>1. 应用自身做到get请求是无副作用的(side-effect free)</h3>
<p>什么是无副作用呢?</p>
<p>我理解是就算是可以请求到结果,也不会带来损失。最基本的也就是不会修改用户的数据。一般遵循http的语义的都会做到这点。如果一些敏感数据不能让人查询到的应该也最好不用get请求来做,举个例子就是对应银行网站,查询用户的基本信息包括余额、交易记录等应该都属于机密信息,那么django去做银行应用的时候,大部分请求都不能是get请求。</p>
<p>嗯,你懂了?也就是django不保护get请求抵御csrf攻击。自求多福!</p>
<h3>2. post请求靠增加csrf_token来抵御csrf攻击</h3>
<p>在post请求的表单中,增加一个csrf_token的字段,该字段隐藏并填写上内容(隐藏了就不影响用户体验)。后台服务会验证这个字段,那么第三方的恶意网站因为无法伪造这个隐藏字段的内容,所以也就能够保证安全。</p>
<p>在细节实现上,django并不是把这个隐藏字段存在db,然后每次和db检查,或者是每个请求都随机生成一个内容,同时保存起来验证等等。django是在第一次访问(get请求)的时候在cookie里加入了csrf-token,然后post请求过去时,他就直接检查form表单里的csrf-token是否和cookie里的csrf-token一致的。</p>
<p>所以django的csrf抵御也是依赖于cookie来做到的。那么cookie是否100%安全呢?那就不清楚了。</p>
<h3>3. ajax</h3>
<p>django单独将了一章节说ajax怎么处理,其实主要是因为每次post请求都增加一个csrf-token会有些麻烦,于是他建议你写到header里去。</p>
<h3>4. django对付csrf是否100%安全?</h3>
<p>99%</p>
<p>为何这么说呢?因为cookie也不是100%安全吧。</p>
<h2>三、移动应用有无csrf风险?</h2>
<br/>
<!--先说下我个人的经历。我最初是用的django搭建的一个面向移动应用的api,登陆那块我是直接继承并重载了django的auth模块,让其的验证逻辑按照我的逻辑进行的验证。同时因为不足够了解django,所以这个csrf防御就比较神奇的跟着django加入了。最初我还不知道csrf,然后在写调用api的例子时就发现了问题,后来折腾比较久才发现了有个csrftoken的东西必须带上。
当时囫囵吞枣,追求的是赶紧跑起来,很长一段时间都没再关注过什么是csrf,csrf有哪些危害等等问题。距离最初做这个快2年时间了,虽然其间花过时间,看过2次,但是都没个彻底思考。我心里一直有一个疑问,移动应用的api真的需要csrf防御么?-->
<p>我们翻回去再看下第一、二章。</p>
<p>第一个问题:cookie该为csrf负责么?</p>
<p>cookie给用户带来方便的同时也引入了风险。但我不认为cookie要为csrf攻击负责,因为实际上从django的实现可以看到抵御csrf攻击的cookie还是起到了很大的作用。</p>
<p>第二个问题:网站A该为csrf负责么?</p>
<p>是的。因为他做好了防范,那么就没有危害了。</p>
<p>第三个问题:浏览器在该为csrf负责么?</p>
<p>是的。浏览器在csrf攻击中,错误的在访问恶意网站B的时候,允许提交表单至网站A,且同时带上了网站A的cookie,从而使攻击者不需要窃取网站A的cookie,转而利用浏览器“借用”了网站A的cookie。</p>
<p>第四个问题:移动应用是否存在csrf风险?</p>
<p>对比移动应用,移动应用也会为了提高用户体验将很多用户的信息缓存下来,存放的位置一般来说不同于浏览器的cookie,以iOS为例,可能是UserDefauts、SQLite、CoreData,那么这些都是别的应用无法访问的(这个由iOS保证),所以别的应用无法类似向对待浏览器一样来发起攻击。当然,移动应用也可以在本机的cookie里存放用户信息,那么此时如果本机的浏览器会存在问题3中提到的,那么一样需要考虑csrf攻击。</p>
</div>
</article>
<article class="post" itemprop="blogPost" itemscope itemtype="http://schema.org/BlogPosting">
<div class="meta">
<div class="date">
<time datetime="2013-11-24T18:13:09+08:00" data-updated="true" itemprop="datePublished">Nov 24<span>th</span>, 2013</time></div>
<div class="tags">
</div>
</div>
<h1 class="title" itemprop="name"><a href="/blog/2013/11/24/new-python-project-1-prepare/" itemprop="url">新python项目–1.准备工作</a></h1>
<div class="entry-content" itemprop="articleBody">
<h2>一、准备python环境</h2>
<p>我的工作机是Mac.而目标服务器应该大都是Ubuntu或者centOS,这2者我更倾向于Ubuntu,所以我将把Mac和Ubuntu下的步骤记录下来。</p>
<h3>1.1 包管理</h3>
<p>Mac下我用的包管理是brew,Ubuntu自带的包管理是apt-get。</p>
<p>pip是python下的包管理,pip如何装请自行google或者bing?</p>
<h3>1.2 virtualenv</h3>
<p>为什么需要virtualenv?</p>
<p>其实之前我一直没有用,但这次可能要用的一些类库的版本可能和现在已有的项目不大一样,所以试试吧。</p>
<p>安装virtualenv及创建一个虚拟环境命令如下:(pyCharm似乎自带这个功能,我没用过,同时需要在pyCharm中简单配置下才可以支持虚拟环境)</p>
<pre><code>$ sudo pip install virtualenv virtualenvwrapper
$ export WORKON_HOME=~/work/python_project
$ mkdir -p $WORKON_HOME
$ source /usr/local/bin/virtualenvwrapper.sh
$ mkvirtualenv env1
</code></pre>
<p>需要退出虚拟环境时</p>
<pre><code>$ deactivate
</code></pre>
<p>需要进入虚拟环境时</p>
<pre><code>$ cd ~/work/python_project/env1
$ source bin/activate
</code></pre>
<p>相关参考:</p>
<ul>
<li><a href="https://pypi.python.org/pypi/virtualenv">virtualenv</a></li>
<li><a href="http://virtualenvwrapper.readthedocs.org/en/latest/">virtualenvwrapper</a>是一个对虚拟环境的一个包装工具。</li>
</ul>
<h3>1.3 django</h3>
<p>之前我用的是django1.3后来升级到1.4,新装的环境一看已经是1.6了,所以这个项目将在django1.6的基础上继续</p>
<pre><code>$ pip install django
</code></pre>
<h3>1.4 djangorestframework</h3>
<p>djangorestframework是我找到的一个在django的基础上提供restful api的框架。版本2.3.9。</p>
<pre><code>$ pip install djangorestframework
</code></pre>
<h3>1.5 MySQLdb</h3>
<p>db是MySQL,python下需要安装MySQLdb。</p>
<p>Ubuntu:</p>
<pre><code>$ sudo apt-get install python-MySQLdb
</code></pre>
<p>我发现Ubuntu的virtualenv下直接装也有问题,所以还是源码包试试吧。<a href="http://downloads.sourceforge.net/project/mysql-python/mysql-python-test/1.2.4b4/MySQL-python-1.2.4b4.tar.gz?r=&ts=1386213050&use_mirror=jaist">下载地址</a></p>
<p>不过Ubuntu下不用改那个配置了,直接敲命令安装即可。</p>
<p>Mac:</p>
<p><em>更新:</em></p>
<p>直接建一个软链</p>
<pre><code>ln -s /usr/local/mysql/bin/mysql_config /usr/local/bin/mysql_config
</code></pre>
<p>因为反复要用,老下包然后改太麻烦</p>
<p>mac下的安装似乎有点问题,简单的pip是装不了的,给个参考按<a href="http://blog.csdn.net/intel80586/article/details/8487682">mac os x 10.8 安装python-mysqldb血泪史</a> 的步骤做就可以了。我装的是MySQL-python-1.2.4b4,其实也不算太麻烦,就是下的源码包,然后修改下配置文件site.cfg</p>
<pre><code>mysql_config = /usr/local/mysql/bin/mysql_config
</code></pre>
<p>如果报错</p>
<pre><code>error: command 'cc' failed with exit status 1
</code></pre>
<p>则运行</p>
<pre><code>export CFLAGS=-Qunused-arguments
export CPPFLAGS=-Qunused-arguments
</code></pre>
<p>来源<a href="http://stackoverflow.com/questions/21638444/error-command-cc-failed-with-exit-status-1-mysqldb-installation-on-mac">stackoverflow</a></p>
<p>修改完了运行命令</p>
<pre><code>$ python setup.py clean
$ python setup.py build
$ python setup.py install
</code></pre>
<p>就可以了,验证是否安装ok,在python下</p>
<pre><code>>>> import MySQLdb
</code></pre>
<p>没异常就是ok了。</p>
<h2>二、数据库</h2>
<p>数据库选择MySQL,此处不再详述安装等过程。关键是这块环境我是已有的,懒得再捣腾,你懂的。</p>
<h2>三、版本库</h2>
<p>我在github上建立了一个开源项目<a href="https://github.com/bitwolaiye/django_rest_api_sample">django_rest_api_sample</a> 用于存储代码。</p>
<p>将项目clone到本地</p>
<pre><code>$ cd env1
$ git clone https://github.com/bitwolaiye/django_rest_api_sample.git
</code></pre>
</div>
</article>
<article class="post" itemprop="blogPost" itemscope itemtype="http://schema.org/BlogPosting">
<div class="meta">
<div class="date">
<time datetime="2013-11-24T18:12:48+08:00" data-updated="true" itemprop="datePublished">Nov 24<span>th</span>, 2013</time></div>
<div class="tags">
</div>
</div>
<h1 class="title" itemprop="name"><a href="/blog/2013/11/24/new-python-project/" itemprop="url">新的python项目</a></h1>
<div class="entry-content" itemprop="articleBody">
<h2>一、想法</h2>
<p>起因是因为要对之前的一部分学习进行总结,可是我对python这块只是简单应用,而非大拿,所以当要自己写点有深度的内容,发现还是相当的乏力。不过回想过去的很长一段时间还是遇到了很多问题同时也解决了问题,把这些问题总结下,也是个收获,还能分享给别人。所以我想就以之前的项目为原型,一步一步把再做一遍,同时回忆回忆问题,再总结总结分享下。</p>
<p>这个项目暂定以宠物社区为目标,搭建面向移动平台、提供后台api的服务。</p>
<p>在这个项目里,用户可以发布带一张图或一段短文本的信息。用户之间可以相互关注,关注后,可以看到被关注者发布的信息。用户可以对信息发表评论,评论后将会给被评论者发送通知。</p>
<p>项目名:pet_api</p>
<h2>二、计划章节</h2>
<br/>
<ol>
<li>准备工作</li>
<li>框架搭建</li>
<li>基本功能实现</li>
<li>部署</li>
</ol>
</div>
</article>
<article class="post" itemprop="blogPost" itemscope itemtype="http://schema.org/BlogPosting">
<div class="meta">
<div class="date">
<time datetime="2013-11-24T14:59:24+08:00" data-updated="true" itemprop="datePublished">Nov 24<span>th</span>, 2013</time></div>
<div class="tags">
</div>
</div>