Tag Archives: 编程

当初看 Dive into Python 的时候就听过装饰器,不过知道是个语法糖,感觉上没什么用,就没仔细了解,这几天看一段代码用到了装饰器,只好再研究下吧。

为什么使用装饰器?

AstralWind 在他的博客里这么说,“装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。”

打个比方,我是个有怪癖的人,在调用任何函数的时候总希望先输出函数的name和doc,因为我常常反复传递函数,所以最好把这个函数的引用计数也显示下?要么把函数运行时间也显示出来吧!

如果不用装饰器,我们可能在写函数的时候把name、doc什么的都print出来,这样有些麻烦,写多少个函数就得copy多少次,利用Python万物皆对象的特性,我们不妨写个函数来做这件事情:

不过这样在调用函数的时候总得先把函数传给PrintDetail(),既不美观也不方便,那么是时候让装饰器登场了:

这里我们定义了装饰器,不过,等等,我运行完发现怎么我还没调用func,他就运行了?
上面这个装饰器是不合格的,如果你尝试去掉用的话,甚至会发现装饰器只会调用一次。
这是因为我们还没弄清楚究竟什么时装饰器,我先提供一个正确的装饰器:

为什么要提供_PrintDetail,而且还要把它返回?
为什么现在看起来就不会没调用自动运行?
为什么现在多次运行都可以自动调用装饰器了?

虽然没有读过Python关于这部分的源码,但是大概可以推测出Python涉及到装饰器时怎么工作的:
Read More →

不知道有没有人喜欢用ctypes,反正我是不大喜欢的。用了ctypes之后程序会显得很凌乱——为了调用c/c++写的dll,动不动c_int或者c_char_p,要是碰上dll里各种用结构体或者数组或者指针的话,那更是悲剧了。想象下先写个c_char_p,然后再pointer(),然后组合起来一个struct,再排出个数组,最后还要获得其指针?

简直就是个悲剧,好了,吐槽完毕,下面说正经的,有一个数据采集仪,提供一个dll方便我们取数据,VC6.0下编译的,某个函数在文档中给出原型如下:

  1. // 功能描述:获取传感器的测量值。   
  2. // 输入参数:pSensorVal,用户分配的用来保存传感器值的数组首地址;   
  3. //           pSensorCount,用户分配的数组长度;   
  4. // 输出参数:pSensorVal,保存采集到的传感器的值;   
  5. //           pSensorCount,分析仪中的传感器数,如果分析仪中的传感器数大于用户指定的个数,则只返回用户指定个数的传感器值。   
  6. // 返 回 值:成功返回1;失败返回负数;   
  7. //           -1:获取失败   
  8. FBGA_DR_API int FBGA_GetSensorVal (SSensorVal *pSensorVal, int *pSensorCount);  

Read More →

最近在做PythonChallenge,挺有意思的,不少都靠谷歌才有了idea,不过代码都是自己写的,记录下,免得将来忘掉。(不要直接用这里的答案来过关哦,Avoid looking for spoilers.)

p.s. 科普:PythonChallenge分0-33共34关,当你开始玩这个游戏时,网站会告诉你第一关的地址以及有关后面关卡的地址的提示,你的任务就是尽量搜集这些有关下一关的地址的线索,然后找到下一关的确切地址(通常需要编程)。听起来有点像寻宝游戏,其实却是差不多。

注:所有程序在Windows XP sp3 + Python 3.2 下调试通过哦,如果涉及到第三方包,则对其版本另作说明。

0. 0.html

话说Hint是try to change URL address,这句话既是提示,也为以后解所有问题奠定了基础。

我刚看到这个hint时,看了一眼地址:0.htm,哦,下意识的就直接把0.htm改成了1.htm虽然不是答案但也不远了——在这个页面里有个提示:2**38 is much much larger.
哦,看来确实要计算0.htm那个图片里的那个2的38次方啊,用python计算得
2**38 = 274877906944
OK,输入274877906944.htm,成功进入第一关。

1. map.html

那个图片提示很明显——凯撒密码,凯撒密码非常常见而且易被破解(特别对于长明文),以前看数论与密码,第一章讲的就是这个。

代码可像我这样用chr(ord())来写,也可以提前写个字典然后用string对象translate()函数(就像字母算术的穷举算法那样)。

代码:

  1. # -*- coding : utf-8 -*-   
  2.   
  3. text = “g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr’q ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj.”   
  4. trans = ”   
  5.   
  6. for ch in text:   
  7.     if ord(ch) >= ord(‘a’) and ord(ch) <= ord(‘z’):   
  8.         trans = trans + (chr(ord(ch) + 2) if ord(ch) + 2 <= ord(‘z’) else chr(ord(ch) + 2 - 26))   
  9.     else:   
  10.         trans = trans + ch   
  11.   
  12. print(trans)  

 

获得的字符串是:“i hope you didnt translate it by hand. thats what computers are for. doing it in by hand is inefficient and that’s why this text is so long. using string.maketrans() is recommended. now apply on the url.”

OK,将text换成map再运行下程序获得ocr即是下一关地址。

2. ocr.html

打开这一关发现页面上没什么有用的东西,于是打开源代码看下“find rare characters in the mess below”,然后下面一大堆字符,ok,按照他所说的写一个统计字符串字符个数的程序:

  1. # -*- coding: utf-8 -*-   
  2.   
  3. strtext = ”’past by your self
  4. ”’  
  5.   
  6. dictwords = {}   
  7.   
  8. for chtemp in strtext:   
  9.     if chtemp in dictwords:   
  10.         dictwords[chtemp] += 1   
  11.     else:   
  12.         dictwords[chtemp] = 1   
  13.   
  14. print(dictwords)  

 

统计结果是:“{‘\n’: 1221, ‘!’: 6079, ‘#’: 6115, ‘%’: 6104, ‘$’: 6046, ‘&’: 6043, ‘)’: 6186, ‘(‘: 6154, ‘+’: 6066, ‘*’: 6034, ‘@’: 6157, ‘[': 6108, ']‘: 6152, ‘_’: 6112, ‘^’: 6030, ‘a’: 1, ‘e’: 1, ‘i’: 1, ‘l’: 1, ‘q’: 1, ‘u’: 1, ‘t’: 1, ‘y’: 1, ‘{‘: 6046, ‘}’: 6105}”

嗯,那就是’a’, ‘e’, ‘i’, ‘l’, ‘q’, ‘u’, ‘t’, ‘y’了。组成个单词——“equality”。
Read More →

这是一个最开始由Raymond Hettinger写的一个解决字母算术(alphametics)问题的程序,其思想是穷举,在这里将我加了注释的版本发出来。主要是找到所有不同字母,然后将所有数字穷举,利用translate()和eval()计算并验证。

  1. import re  
  2. import itertools  
  3.   
  4. def solve(puzzle):   
  5.     words = re.findall(‘[a-z]+’, puzzle.upper())                        # 找到谜题中所有字母   
  6.     unique_characters = set(”.join(words))                             # 找到所有出现的不同字母   
  7.     assert len(unique_characters) <= 10, ‘too many letters’             # 如果超过10个不同字母则返回字幕太多   
  8.     first_letters = {word[0] for word in words}                         # 将参与计算的元素的第一位分离出来   
  9.     n = len(first_letters)                                              # 用n统计共有多少个参与计算的元素   
  10.     sorted_characters = ”.join(first_letters) + \   
  11.         ”.join(unique_characters - first_letters)                      # 将所有参与运算的字母按“首字母+其他字母”组合   
  12.     characters = tuple(ord(c) for c in sorted_characters)               # 将字母转换成ascii码值   
  13.     digits = tuple(ord(c) for c in ’0123456789′)                        # 将数字转化成ascii码值   
  14.     zero = digits[0]   
  15.     for guess in itertools.permutations(digits, len(characters)):       # 用itertools.permutations生成所有可能   
  16.         if zero not in guess[:n]:   
  17.             equation = puzzle.translate(dict(zip(characters, guess)))   # 用translate把原字符串进行替换   
  18.             if eval(equation):                                          # 检测是否正确   
  19.                 return equation   
  20.   
  21. if __name__ == ‘__main__‘:   
  22.     import sys  
  23.     sys.argv.append(‘send + more == money’)                             # 在我的系统里sys.argv[1] = [], so…   
  24.     for puzzle in sys.argv[1:]:   
  25.         print(puzzle)   
  26.         solution = solve(puzzle)   
  27.         if solution:   
  28.             print(solution)  

 

照例把我的运行结果放出来(AMD Athlon TK-55,运行时CPU占用50%左右)

image Read More →

”’在各种Python的书里翻了N多,最后还是选择了Dive into Python

话说刚开始打算看的就是Dive into Python,但是果断被那个恐怖的“第一个程序”吓住了,因为python处理字符串什么太过灵活以至于完全没有看懂,又在网上看到好多这本书的负面评论[1],于是就把这本书放下了。之后翻过《可爱的python》——发现果然不是我这种毫无脚本语言基础的人看得,翻了A byte of PythonBeginning Python From Novice to Professional 感觉这些书还是写的太细了,看着很没意思,毕竟我以前学过的编程语言也不少了,虽然没有脚本语言……不过Beginning Python From Novice to Professional 的项目时间部分看起来不错,有时间还是想看看。另外一个问题就是有的书不错但翻译不行或者是python2.x版本的书,经过层层筛选,最后决定看Python v3.0c1 documentation里的Tutorial,简洁,而且是3.0的版本,还是中英对照,怎么看都是理想的选择……但是,当我看到Data Structures时我终于受不了了,这也太简洁了,感觉什么都没说清嘛!而且程序的排版越来越差也真是让人难以忍受。晚上虽然没决定要看什么,但是随手在平板里点开了Dive into Python,发现这第一个程序其实不难啊,稍稍熟悉了脚本语言和Python简洁的风格我就发现已经能看懂这本书了,再往下翻感觉这本书其实既不罗嗦又不缺料,很适合我看啊,于是决定再翻开DiP…

”’

以上是一个Python风格的docstring。

DiP3的第一个程序:

  1. suffix = {1000: ['kb', 'mb', 'gb', 'tb', 'pb', 'eb', 'zb', 'yb'],   
  2.           1024: ['kib', 'mib', 'gib', 'tib', 'pib', 'eib', 'zib', 'yib']}   
  3.   
  4. def approximate_size(size, a_kilobyte_is_1024_bytes = true):   
  5.     ”’convert a file size to human-readable form.  
  6.  
  7.     keyword arguments:  
  8.     size                –  file size in bytes  
  9.     a_kilobyte_is_1024_bytes    –  if true(default), use multiples of 1024  
  10.                         if false, use multiples od 1000  
  11.     returns: string  
  12.     ”’  
  13.   
  14.     if size &lt; 0:   
  15.         raise valueerror(‘number must be non-negative’)   
  16.   
  17.     multiple = 1024 if a_kilobyte_is_1024_bytes else 1000   
  18.   
  19.     for suffix in suffix[multiple]:   
  20.         size /= multiple   
  21.         if size &lt; multiple:   
  22.             return ‘{0:.1f} {1}’.format(size, suffix)   
  23.   
  24.     raise valueerror(‘number too large’)   
  25.   
  26. if __name__ == ‘__main__‘:   
  27.         print(approximate_size(1000000000000, false))   
  28.         print(approximate_size(1000000000000))  

顺便show下Sublime Text的着色效果,真心很好看。

clip_image001

最坑的地方是一开始把if __name__ == ‘__main__’:的缩进位置打错了,怎么都出不了结果,郁闷死了……

Footnotes:
[1] 赖勇浩 为什么《Dive into Python》不值得推荐 Read More →