使用 python 分析一串文本中的双字母组
Using python to analyse bigrams in a string of text
我正在尝试使用 python 来帮助我破解 Vigenère 密码。我对编程还很陌生,但我已经设法制作了一种算法来分析一串文本中的二元组频率。这是我目前所拥有的:
import nltk, string
from nltk import bigrams
Ciphertext = str(input("What is the text to be analysed?"))
#Removes spacing and punctuation to make the text easier to analyse
def Remove_Formatting(str):
str = str.upper()
str = str.strip()
str = str.replace(' ','')
str = str.translate(str.maketrans({a:None for a in string.punctuation}))
return str
Ciphertext = Remove_Formatting(Ciphertext)
#Score is meant to increase if most common bigrams are in the text
def Bigram(str):
Common_Bigrams = ['TH', 'EN', 'NG',
'HE', 'AT', 'AL',
'IN', 'ED', 'IT',
'ER', 'ND', 'AS',
'AN', 'TO', 'IS',
'RE', 'OR', 'HA',
'ES', 'EA', 'ET',
'ON', 'TI', 'SE',
'ST', 'AR', 'OU',
'NT', 'TE', 'OF']
Bigram_score = int(0)
for bigram in str:
if bigram in Common_Bigrams:
Bigram_score += 1
return Bigram_score
Bigram(Ciphertext)
print (Bigram_score)
然而,当我尝试 运行 使用文本时,我得到了这个错误:
Traceback (most recent call last):
File "C:/Users/Tony/Desktop/Bigrams.py", line 36, in <module>
print (Bigram_score)
NameError: name 'Bigram_score' is not defined
这是什么意思?我以为我已经将 Bigram_score 定义为一个变量,而且我已经尝试了所有方法,但它仍然 returns 是这样或那样的错误。我做错了什么?请帮忙...
提前致谢,
托尼
您可以使 Bigram_score 全局化,如下所示:
def Bigram(string): # don't override str
global Bigram_score
Common_Bigrams = ['TH', 'EN', 'NG',
'HE', 'AT', 'AL',
'IN', 'ED', 'IT',
'ER', 'ND', 'AS',
'AN', 'TO', 'IS',
'RE', 'OR', 'HA',
'ES', 'EA', 'ET',
'ON', 'TI', 'SE',
'ST', 'AR', 'OU',
'NT', 'TE', 'OF']
Bigram_score = 0 # that 0 is an integer is implicitly understood
for bigram in string:
if bigram in Common_Bigrams:
Bigram_score += 1
return Bigram_score
您还可以将 Bigram
函数的返回结果绑定到一个变量,如下所示:
Bigram_score = Bigram(Ciphertext)
print(Bigram_score)
或:
print(Bigram(Ciphertext))
当您为函数中的变量赋值时,它们是局部的并绑定到该函数。如果一个函数 returns 任何东西,返回值必须绑定到一个变量才能正确重用(或直接使用)。
这是其工作原理的示例:
spam = "spam" # global spam variable
def change_spam():
spam = "ham" # setting the local spam variable
return spam
change_spam()
print(spam) # prints spam
spam = change_spam() # here we assign the returned value to global spam
print(spam) # prints ham
此外,您的 for 循环循环遍历一元语法而不是二元语法。让我们仔细看看:
for x in "hellothere":
print(x)
这将打印 unigrams。因此,我们重命名您代码中的 bigram
变量,以查看哪里存在逻辑问题。
for unigram in string:
if unigram in Common_Bigrams:
print("bigram hit!")
因为没有与任何双字母相同的单字母,所以永远不会打印 "bigram hit!"
。我们可以尝试使用 while 循环和索引号,通过不同的方法获得二元语法。
index = 0
n = 2 # for bigrams
while index < len(string)-(n-1): # minus the length of n-1 (n-grams)
ngram = string[index:index+n] # collect ngram
index += 1 # important to add this, otherwise the loop is eternal!
print(ngram)
接下来,只需在循环中包含您想对二元组执行的操作即可。
我正在尝试使用 python 来帮助我破解 Vigenère 密码。我对编程还很陌生,但我已经设法制作了一种算法来分析一串文本中的二元组频率。这是我目前所拥有的:
import nltk, string
from nltk import bigrams
Ciphertext = str(input("What is the text to be analysed?"))
#Removes spacing and punctuation to make the text easier to analyse
def Remove_Formatting(str):
str = str.upper()
str = str.strip()
str = str.replace(' ','')
str = str.translate(str.maketrans({a:None for a in string.punctuation}))
return str
Ciphertext = Remove_Formatting(Ciphertext)
#Score is meant to increase if most common bigrams are in the text
def Bigram(str):
Common_Bigrams = ['TH', 'EN', 'NG',
'HE', 'AT', 'AL',
'IN', 'ED', 'IT',
'ER', 'ND', 'AS',
'AN', 'TO', 'IS',
'RE', 'OR', 'HA',
'ES', 'EA', 'ET',
'ON', 'TI', 'SE',
'ST', 'AR', 'OU',
'NT', 'TE', 'OF']
Bigram_score = int(0)
for bigram in str:
if bigram in Common_Bigrams:
Bigram_score += 1
return Bigram_score
Bigram(Ciphertext)
print (Bigram_score)
然而,当我尝试 运行 使用文本时,我得到了这个错误:
Traceback (most recent call last):
File "C:/Users/Tony/Desktop/Bigrams.py", line 36, in <module>
print (Bigram_score)
NameError: name 'Bigram_score' is not defined
这是什么意思?我以为我已经将 Bigram_score 定义为一个变量,而且我已经尝试了所有方法,但它仍然 returns 是这样或那样的错误。我做错了什么?请帮忙...
提前致谢,
托尼
您可以使 Bigram_score 全局化,如下所示:
def Bigram(string): # don't override str
global Bigram_score
Common_Bigrams = ['TH', 'EN', 'NG',
'HE', 'AT', 'AL',
'IN', 'ED', 'IT',
'ER', 'ND', 'AS',
'AN', 'TO', 'IS',
'RE', 'OR', 'HA',
'ES', 'EA', 'ET',
'ON', 'TI', 'SE',
'ST', 'AR', 'OU',
'NT', 'TE', 'OF']
Bigram_score = 0 # that 0 is an integer is implicitly understood
for bigram in string:
if bigram in Common_Bigrams:
Bigram_score += 1
return Bigram_score
您还可以将 Bigram
函数的返回结果绑定到一个变量,如下所示:
Bigram_score = Bigram(Ciphertext)
print(Bigram_score)
或:
print(Bigram(Ciphertext))
当您为函数中的变量赋值时,它们是局部的并绑定到该函数。如果一个函数 returns 任何东西,返回值必须绑定到一个变量才能正确重用(或直接使用)。
这是其工作原理的示例:
spam = "spam" # global spam variable
def change_spam():
spam = "ham" # setting the local spam variable
return spam
change_spam()
print(spam) # prints spam
spam = change_spam() # here we assign the returned value to global spam
print(spam) # prints ham
此外,您的 for 循环循环遍历一元语法而不是二元语法。让我们仔细看看:
for x in "hellothere":
print(x)
这将打印 unigrams。因此,我们重命名您代码中的 bigram
变量,以查看哪里存在逻辑问题。
for unigram in string:
if unigram in Common_Bigrams:
print("bigram hit!")
因为没有与任何双字母相同的单字母,所以永远不会打印 "bigram hit!"
。我们可以尝试使用 while 循环和索引号,通过不同的方法获得二元语法。
index = 0
n = 2 # for bigrams
while index < len(string)-(n-1): # minus the length of n-1 (n-grams)
ngram = string[index:index+n] # collect ngram
index += 1 # important to add this, otherwise the loop is eternal!
print(ngram)
接下来,只需在循环中包含您想对二元组执行的操作即可。