Don’t do things the hardest way

Given a DNA sequence, say DNA = ‘AATTGGCCA’, count how many times a given nucleotide (e.g. ‘A’) appears.

I used to do this in Python:

>>>DNA = 'AATTGGCCA'
>>> len(filter(lambda x: x=='A',DNA))
3

Today, I just find out I can simply do:

>>> DNA.count('A')
3

Feel silly myself, but begin to love Python even more!

Python统计DNA序列中长度为n的子序列频率

ms是我师弟的rotation project:
给定一堆DNA序列,即由字符A, C, G, T组成的字符串,统计所有长度为n的子序列出现的频率。
比如 ACGTACGT,子序列长度为2,于是 AC=2, CG=2, GT=2, TA=1,其余长度为2的子序列频率为0.

最先想到的就是建一个字典,key是所有可能的子序列,value是这个子序列出现的频率。
但是当子序列比较长的时候,比如 n=8,需要一个有65536 (4的8次方) 个key-value pair的字典,且每个key的长度是8字符。这样ms有点浪费内存。。

于是想到,所有的长度为n的子序列是有序且连续的,所以可以映射到一个长度为4的n次方的的list里。
令 A=0, C=1, G=2, T=3,则把子序列 ACGT 转换成 0*4^3 + 1*4^2 + 2*4 + 3 = 27, 映射到list的第27位。
如此,list的index对应子序列,而list这个index位置则储存这个子序列出现的频率。

于是我们先要建立2个字典,表示ACGT和0123一一对应的关系:

i2mD = {0:'A', 1:'C', 2:'G', 3:'T'}
m2iD = dict(A=0,C=1,G=2,T=3)
# This is just another way to initialize a dictionary

以及下面的子序列映射成整数函数:

def motif2int(motif):
    '''convert a sub-sequence/motif to a non-negative integer'''
    total = 0
    for i, letter in enumerate(motif):
        total += m2iD[letter]*4**(len(motif)-i-1)
    return total

Test:

>>> motif2int('ACGT')
27

虽然我们内部把子序列当成正整数来存储(确切地说,其实这个整数是没有存在内存里的,而是由其在list的index表示的),为了方便生物学家们看,输出时还是转换回子序列比较好。

于是有了下面的整数映射成子序列函数,其中调用了另外一个函数baseN(),来源在此,感谢作者~

def baseN(n,b):
    '''convert non-negative decimal integer n to
    equivalent in another base b (2-36)'''
    return ((n == 0) and  '0' ) or ( baseN(n // b, b).lstrip('0') + \
    "0123456789abcdefghijklmnopqrstuvwxyz"[n % b])

def int2motif(n, motifLen):
    '''convert non-negative integer n to a sub-sequence/motif with length motifLen'''
    intBase4 = baseN(n,4)
    return ''.join(map(lambda x: i2mD[int(x)],'0'*(motifLen-len(intBase4))+intBase4))

Test:

>>> int2motif(27,4)
'ACGT'

以下代码从命令行读入一个存有DNA序列的fasta文件,以及子序列长度,并输出子序列和频率。注意以下代码需要Biopython module。

if __name__ == '__main__':
    import sys
    from Bio import SeqIO

    # read in the fasta file name and motif length
    # from command line parameters
    fastafile = sys.argv[1]
    motifLen = int(sys.argv[2])

    # list to store subsequence frequency
    frequencyL = [0]*4**motifLen

    # go over each DNA sequence in the fasta file
    # and count the frequency of subsequences
    it = SeqIO.parse(open(fastafile),'fasta')
    for rec in it:
        chrom = rec.seq.tostring()
        for i in range(len(chrom)-motifLen+1):
            motif = chrom[i:i+motifLen]
            frequencyL[motif2int(motif)] += 1

    # print frequency result to screen
    for i, frequency in enumerate(frequencyL):
        print int2motif(i, motifLen), frequency

测试文件 python源代码

可以在终端输入

python frequency.py test.fa 2

则会输出:
AA 0
AC 0
AG 0
AT 4
CA 2
CC 1
CG 0
CT 0
GA 0
GC 4
GG 0
GT 0
TA 0
TC 0
TG 4
TT 0

旧旧旧文一篇: 再论独孤九剑

今日百度出来的。。。
http://club.163.com/viewElite.m?catalogId=135082&eliteId=135082_100d2c9dca90014

此文是高中英语课作业,因为我们英语老师立剑同学对独孤九剑和英语学习的关系有很深的研究,故上课发了盗版的《笑傲江湖》片段,让大家写读后感。。
——–

再论独孤九剑

马昭荣

很早我就拜读过金庸的《笑傲江湖》,深为其中讲述的独孤九剑所折服,一招之间便能刺瞎15人的眼睛,真是出神入化。上学期的一节英语选修课上,我第一次听说独孤九剑居然和学习有关,甚至与只动口不动手的英语学习沾亲带故,令我耳目一新,豁然开朗。之后我写了一点文字,表达我对独孤九剑与英语学习的关系的理解。最近,我第三次读了《笑傲江湖》第十回,偶有所得,欣然忘食,一吐为快。

从风清扬传授令狐冲独孤九剑的话语中,我们可以看出独孤九剑的剑理大致有以下4点:

顺其自然。(“剑术之道,讲究如行云流水,任意所至。”“风清扬道:“一切须当顺其自然。行乎其不得不行,止乎其不得不止,倘若串不成一起,也就罢了,总之并不可有半点勉强。”)

无招胜有招。(风清扬道:“活学活使,只是第一步。要做到出手无招,那才真是踏入了高手的境界。你说‘各招浑成,敌人便无法可破’,这句话还只说对了一小半。不是‘浑成’,而是根本无招。你的剑招使得再浑成,只要有迹可寻,敌人便有隙可乘。但如你根本并无招式,敌人如何来破你的招式?”)

料敌机先。(风清扬拍手赞道:“对,对!孺子可教。‘料敌机先’这四个字,正是这剑法的精要所在,任何人一招之出,必定有若干征兆。……)

不被剑法拘束。(风清扬道:“你倒也不可妄自菲薄,独孤大侠是绝顶聪明之人,学他的剑法,要旨是在一个‘悟’字,决不在死记硬记。等到通晓了这九剑的剑意,则无所施而不可,便是将全部变化尽数忘记,也不相干,临敌之际,更是忘记得越干净彻底,越不受原来剑法的拘束。……”心想:“……他教我剑法之时,总是说‘人使剑法,不是剑法使人’,总说‘人是活的,剑法是死的,活人不可给死剑法所拘’。……”)

由此观之,在英语学习中很多地方都可以用到独孤九剑的剑理。

顺其自然,可以理解为要遵循事物的客观规律,比如背单词,不必每天抱着字典咬文嚼字,痛苦不堪。对于新的词汇,只要多看、多用,自然就会了。又如背课文,也不用机械的记忆,先理清文章的思路,再熟悉一些关键的句子,试着背几遍就水到渠成。推而广之,在其他学科的学习中也是如此。像做物理题,只要掌握了解题规律,看见一道题就能知道它的实质,再按照步骤便很轻易地解决了。

无招胜有招,我觉得这种境界太高了,我还无法完全理解。我认为把它演绎到英语学习中,可能是指知识的网络要全面,细致,以至无隙可乘。这样,无论考试出什么题,都可出奇制胜。我们一旦领会了英语的精髓,自然不必拘泥于其单词、语法了。所以说,有时与其对着一大堆令人眼花缭乱的语法不知所措,不如培养自己的语感,这样即使不知道语法,答题也十拿九稳。

料敌机先说的也许是一种应考策略。即在考试前推测一下重点考察的会是什么内容,然后有针对性的复习。这需要的不仅是学习能力了,还要求有敏锐的洞察力,能够根据满楼的风推断欲来的山雨。对此,我不能借鉴很多,还是脚踏实地的学习为好。这种投机取巧的行为风险太大,好比在武侠小说中,一个人举刀要砍我的脑袋,我却料敌机先以为他要砍我的腿,于是去防守下盘,结果当然是脑袋难保。

不受剑法拘束,用到英语学习上就是不受课本拘束了。尽管我们现在的英语学习和考试是以课本为主,但我们不应教条主义,照本宣科,而要领会课本的精神实质,真正学到自己的东西,达到融会贯通,得心应手的境界。因为课本好比拐杖,当我们学会走路的时候,拐杖自是要扔掉的。我觉得这一点是很重要的人生哲理。社会时刻在变化,所以我们要学会灵活变通。坚持做人的基本原则,具体情况下怎么办那是随便。于是想到笑傲江湖里风清扬与令狐冲的一段对话。现摘录如下:

风清扬微笑道:“你用这法子取得了一日一夜,竟不费半点力气,只不过有点儿卑鄙无耻。”令狐冲笑道:“对付卑鄙无耻之徒,说不得,只好用点卑鄙无耻的手段。”风清扬正色道:“要是对付正人君子呢?”令狐冲一怔,道:“正人君子?”一时答不出话来。风清扬双目炯炯,瞪视着令狐冲,森然问道:“要是对付正人君子,那便怎样?”令狐冲道:“就算他真是正人君子,倘若想要杀我,我也不能甘心就戮,到了不得已的时候,卑鄙无耻的手段,也只好用上这么一点半点了。”风清扬大喜,朗声道:“好,好!你说这话,便不是假冒为善的伪君子。大丈夫行事,爱怎样便怎样,行云流水,任意所至,甚么武林规矩,门派教条,全都是放他妈的狗臭屁!”

我想,规矩是人定的,在极端情况下,违反一些社会上的道德规范也不能算错(当然现在是法制社会,违反法律还是要受到制裁),关键是要问心无愧。

恩,跑题了。最后谈谈我认为的令狐冲学会独孤九剑的原因。我觉得人的要素有三点:明师、贤徒、对手。明师自是指风清扬。要是没有他这样善于启发的老师,令狐冲肯定是学不会独孤九剑的。令狐冲自身的原因也很重要。他记忆力很好,悟性很高,而且性格放荡不羁,这些对他学剑是很有帮助的。另外还得感谢田伯光。他在令狐冲初学时充当了义务陪练,使令狐冲学剑有了明确的目标,在这个目标的激励下,令狐冲自然非常用功,以至进步神速。还有一个非人的因素是理论与实践的紧密结合。君不见,令狐冲学剑时,先聆听风清扬的理论教育,受到理性的冲击。之后便和田伯光实践,巩固理论知识,得到感性的认识。由此可见,理论与实践如同一个人的两只手,是相辅相成的。上述原因我想也可以运用到我们的学习中,但限于篇幅这里不详述了。

金庸的武学博大精深,独孤九剑只算是沧海一粟,我们今后读武侠的时候要善于发现总结,以期能促进我们的英语学习。

谢谢。

作者:incognita【轩辕聿雪】
※ 来源: 网易虚拟社区 北京站.
※ sandralam7888 改变保留标记: 2002.01.21 19:15.

Python语言的诡异特性

Strangest language feature这篇讨论里看到的,原文让人大开眼界啊!

这里抄几个Python的:

>>> def f():
...     try:
...         return True
...     finally:
...         return False
...
>>> f()

你说结果是啥呢?

答案是False!原文的解释是:finally always wins..

_____________________________

>>> (10 > 5 > 1)
True
>>> ((10 > 5) > 1)
False

这个是因为Python允许连续的比较运算,所以 10>5>1 相当于 10>5 and 5>1,于是True。

而 (10>5) > 1 要先运算10>5,结果是True,True被转换成1进行比较,1>1,于是False。

_____________________________

在Python 2.x 里:

>>> True = False
>>> True
False

把False赋值给True,True的值就变成了False = =!
在Python 3.x 里就不能这样做了。

_____________________________

>>> a = "foo" "bar"
>>> a
'foobar'

在Ruby, C里ms也是这样。虽然我不知道这个特性有啥用处。

_____________________________

>>> a[0] = "hello"
NameError: name 'a' is not defined
>>> a[0:] = "hello"
NameError: name 'a' is not defined
>>> a = []
>>> a[0] = "hello"
IndexError: list assignment index out of range
>>> a[0:] = "hello"
>>> a
['h', 'e', 'l', 'l', 'o']

上面把 a[0:] 改成 a[:] 或 a[42:] 或 a[:33] 同样work!

_____________________________

今天自己遇到的:

>>> a=[0]*10
>>> a
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> a[3:5] += [2]*2
>>> a
[0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0]
>>> a[3:5] += [3]*2
>>> a
[0, 0, 0, 0, 0, 3, 3, 2, 2, 0, 0, 0, 0, 0]

我没想到是这个结果,+= 相当于做了insert的事情,而不是改变list原位置elements的值

一个workarround是用numpy,把a变成array:

>>> import numpy
>>> a=numpy.zeros(10)
>>> a
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])
>>> a[3:5] += [2]*2
>>> a
array([ 0.,  0.,  0.,  2.,  2.,  0.,  0.,  0.,  0.,  0.])
>>> a[3:5] += [3]*2
>>> a
array([ 0.,  0.,  0.,  5.,  5.,  0.,  0.,  0.,  0.,  0.])

大家知道有啥更好的方法么?

_____________________________

又遇到一个:

>>> L = [0]*10
>>> L
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> L[0] += 1
>>> L
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

>>> L = [[]]*10
>>> L
[[], [], [], [], [], [], [], [], [], []]
>>> L[0].append(1)
>>> L
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]

解决方法:

>>> L = []
>>> for i in range(10):
...     L.append([])
...
>>> L
[[], [], [], [], [], [], [], [], [], []]
>>> L[0].append(1)
>>> L
[[1], [], [], [], [], [], [], [], [], []]

此文对此有详细讨论

外婆的笑话

1. 小姨和我小姨夫谈他们上大学的儿子。
小姨对我小姨夫说,儿子都这么大了,你就别管了。
小姨夫说,好吧,你爱当后娘那我也当次后爹。
外婆听到了,对小姨夫怒道:你做梦都想要个后娘啊!
小姨夫汗道,你不是耳背么?关键时候听得挺清楚啊。。

2. 外婆摔了一跤,摔断了手腕。
小姨让她去医院,外婆说,被跳蚤踢了一下,哪至于住院啊。
小姨夫说,那跳蚤得多大啊。

(未完待续)

外一:
今天我爸开车放在倒档熄火了,再准备打火却拧不动钥匙。
我小姨夫喊:放屁,放屁!不放屁打不着火!
我就纳闷了,难道屁是可燃气体?
半天才反应过来,原来小姨夫的意思是放在P档。

翻页: 1 2 3 4 5 6 ...83 84 85 往后翻