68、“Metathesis”指的是单词中字母的换位。如果两个单词可以通过交换其中两个字母相互转换,那么这两个单词就构成一个“换位对”,例如“converse”和“conserve”。编写一个程序,找出单词列表中所有的换位对。
以下是一个Python程序,用于找出单词列表中所有的换位对:
# 假设word_list是包含所有单词的列表
word_list = [] # 这里需要你实际填充单词列表
# 函数用于检查两个单词是否是换位对
# 首先检查两个单词是否是变位词(字母相同但顺序不同)
# 然后检查是否可以通过交换两个字母将一个单词转换为另一个单词
# 使用zip函数同时遍历两个单词的对应字母
# 找出不同字母的位置,如果不同字母的位置只有两个且交换后能使两个单词相同,则是换位对
def is_metathesis_pair(word1, word2):
if sorted(word1) != sorted(word2):
return False
diffs = []
for i, (c1, c2) in enumerate(zip(word1, word2)):
if c1 != c2:
diffs.append(i)
return len(diffs) == 2 and word1[diffs[0]] == word2[diffs[1]] and word1[diffs[1]] == word2[diffs[0]]
# 找出所有的换位对
metathesis_pairs = []
# 遍历单词列表,对每两个不同的单词进行检查
for i in range(len(word_list)):
for j in range(i + 1, len(word_list)):
if is_metathesis_pair(word_list[i], word_list[j]):
metathesis_pairs.append((word_list[i], word_list[j]))
# 输出所有的换位对
for pair in metathesis_pairs:
print(pair)
代码解释:
is_metathesis_pair
函数
:
– 首先检查两个单词是否是变位词,通过对两个单词的字母进行排序并比较来实现。如果不是变位词,直接返回
False
。
– 然后使用
zip
函数同时遍历两个单词的对应字母,找出不同字母的位置。
– 如果不同字母的位置只有两个,并且交换这两个位置的字母后两个单词相同,则返回
True
,表示这两个单词是换位对。
主程序
:
– 遍历单词列表,对每两个不同的单词调用
is_metathesis_pair
函数进行检查。
– 如果是换位对,则将它们添加到
metathesis_pairs
列表中。
– 最后输出所有的换位对。
注意事项:
代码中的
word_list
需要你根据实际情况填充单词列表。
该程序的时间复杂度是$O(n^2 * m)$,其中$n$是单词列表的长度,$m$是单词的平均长度。
69、在add_bigram函数中,if语句会根据键是否已经存在于字典中来创建一个新列表或向现有列表追加一个元素。字典提供了一个名为setdefault的方法,使用setdefault方法重写add_bigram函数,并说明setdefault方法是如何工作的。
以下是使用
setdefault
方法重写
add_bigram
函数的示例。
原
add_bigram
函数如下:
successor_map = {}
def add_bigram(bigram):
first, second = bigram
if first not in successor_map:
successor_map[first] = [second]
else:
successor_map[first].append(second)
使用
setdefault
方法重写后的代码:
successor_map = {}
def add_bigram(bigram):
first, second = bigram
successor_map.setdefault(first, []).append(second)
setdefault
方法的作用是:
如果字典中已经存在指定的键,则返回该键对应的值;
如果键不存在,则在字典中插入该键,并将其值设置为指定的默认值(这里是一个空列表
[]
),然后返回这个默认值。
这样就可以更简洁地实现原
add_bigram
函数的功能。
70、编写一个函数来统计每个三元组(三个单词的序列)出现的次数。提示:编写一个名为count_trigram的函数,它类似于统计二元组的函数。然后编写一个名为process_word_trigram的函数,它类似于处理二元组单词的函数。
# 用于存储三元组及其出现次数的字典
trigram_counter = {}
# 用于跟踪当前三个连续单词的列表
window = []
# 统计三元组出现次数的函数
def count_trigram(trigram):
key = tuple(trigram)
if key not in trigram_counter:
trigram_counter[key] = 1
else:
trigram_counter[key] += 1
# 逐个处理单词的函数
def process_word_trigram(word):
window.append(word)
if len(window) == 3:
count_trigram(window)
window.pop(0)
71、现在让我们实现马尔可夫链文本分析,建立从每个三元组(trigram)到可能后续词列表的映射。编写一个名为
add_trigram
的函数,该函数接受一个包含三个单词的列表,并使用前两个单词作为键,第三个单词作为可能的后续词,在
successor_map
中添加或更新一个条目。
add_trigram
successor_map
def add_trigram(trigram):
first, second, third = trigram
key = (first, second)
if key not in successor_map:
successor_map[key] = [third]
else:
successor_map[key].append(third)
72、临时程序和持久程序之间有什么区别?
临时程序通常运行时间较短,结束时其数据会丢失,每次运行时都从头开始;而持久程序会运行很长时间(或一直运行),至少会将部分数据存储在长期存储设备中,并且在关闭并重新启动后能从上次停止的地方继续运行。
73、相对路径和绝对路径有什么区别?
相对路径是从当前工作目录或其他指定目录开始的路径,例如像
memo.txt
这样简单的文件名就是相对路径,它指定的文件名是相对于当前目录的。在当前目录为
/home/dinsdale
的例子中,
memo.txt
等同于完整路径
/home/dinsdale/memo.txt
。
而绝对路径是不依赖于当前目录的路径,以
/
开头,例如
/home/dinsdale
就是一个绝对路径。
要找到文件的绝对路径,可以使用
os.path.abspath
函数。
74、什么是哈希函数?
A hash function is a function that takes an object and computes an integer that is used to locate a key in a hash table. It can also take the contents of a file and compute a digest, which is usually a large integer. If two files contain the same data, they will have the same digest. If two files differ, they will almost always have different digests. In Python, the
hashlib
module provides several hash functions, such as
md5
.
75、什么是MD5摘要?
MD5摘要可以通过
hexdigest
方法得到,它是一个由十六进制数字组成的字符串,代表一个以16为基数的整数。
在Python中,可通过
hashlib
模块的
md5
函数来计算。首先使用
hashlib.md5()
创建一个
HASH
对象,读取文件内容后用
update
方法更新该对象,最后使用
hexdigest
方法得到MD5摘要。
例如,以下代码展示了如何计算文件的MD5摘要:
import hashlib
def md5_digest(filename):
data = open(filename, "rb").read()
md5_hash = hashlib.md5()
md5_hash.update(data)
digest = md5_hash.hexdigest()
return digest
如果两个文件包含相同的数据,它们将具有相同的MD5摘要;如果两个文件不同,它们几乎总是会有不同的MD5摘要。
76、编写一个名为replace_all的函数,该函数接受一个模式字符串、一个替换字符串和两个文件名作为参数。它应该读取第一个文件,并将内容写入第二个文件(必要时创建该文件)。如果模式字符串出现在内容的任何位置,都应该用替换字符串替换它。为了测试你的函数,读取photos/notes.txt文件,并将其中的photos替换为images。
以下是实现
replace_all
函数的Python代码:
def replace_all(pattern, replacement, file1, file2):
try:
# 打开第一个文件以读取内容
with open(file1, 'r') as f1:
content = f1.read()
# 替换模式字符串为替换字符串
new_content = content.replace(pattern, replacement)
# 打开第二个文件以写入内容,必要时创建文件
with open(file2, 'w') as f2:
f2.write(new_content)
print(f'已将 {pattern} 替换为 {replacement},并将结果写入 {file2}')
except FileNotFoundError:
print(f'文件 {file1} 未找到。')
# 测试函数
replace_all('photos', 'images', 'photos/notes.txt', 'photos/notes_replaced.txt')
这段代码定义了
replace_all
函数,它首先打开第一个文件并读取其内容,然后使用
replace
方法将模式字符串替换为替换字符串,最后将替换后的内容写入第二个文件。如果第一个文件不存在,会捕获
FileNotFoundError
并输出错误信息。测试部分调用了该函数,将
photos/notes.txt
文件中的
photos
替换为
images
,并将结果写入
photos/notes_replaced.txt
文件。
77、编写一个名为
add_word
的函数,该函数接受一个字符串和一个
shelf
对象作为参数。函数需要对传入字符串的字母进行排序以生成一个键,然后检查该键是否已经存在于
shelf
中。如果不存在,就创建一个包含该字符串的列表并将其添加到
shelf
中;如果存在,就将该字符串追加到现有的值中。
add_word
shelf
shelf
shelf
import shelve
def sort_word(word):
return ''.join(sorted(word))
def add_word(word, shelf):
key = sort_word(word)
if key not in shelf:
shelf[key] = [word]
else:
anagram_list = shelf[key]
anagram_list.append(word)
shelf[key] = anagram_list
return shelf
# 测试代码
word = 'pots'
word2 = 'tops'
# 创建一个新的空shelf
anagram_map = shelve.open('anagram_map', 'n')
# 添加第一个单词
add_word(word, anagram_map)
print(anagram_map[sort_word(word)])
# 添加第二个单词
add_word(word2, anagram_map)
print(anagram_map[sort_word(word)])
anagram_map.close()
78、为了识别图像文件,请编写一个名为is_image的函数,该函数接受一个路径和一个文件扩展名列表作为参数。如果路径以列表中的某个扩展名结尾,则返回True。提示:使用os.path.splitext来编写这个函数。
import os
def is_image(path, extensions):
_, ext = os.path.splitext(path)
return ext.lower() in ['.' + e.lower() for e in extensions]
79、编写一个名为add_path的函数,该函数接受一个路径和一个shelf对象作为参数。它应该使用md5_digest来计算文件内容的摘要。然后更新shelf,要么创建一个新的项,将摘要映射到包含该路径的列表,要么如果该列表已经存在,则将路径追加到该列表中。
import hashlib
def md5_digest(path):
md5_hash = hashlib.md5()
with open(path, 'rb') as file:
for chunk in iter(lambda: file.read(4096), b''):
md5_hash.update(chunk)
return md5_hash.hexdigest()
def add_path(path, shelf):
digest = md5_digest(path)
if digest not in shelf:
shelf[digest] = [path]
else:
shelf[digest].append(path)
80、编写一个名为process_path的函数,该函数接受一个路径、一个用于存储文件信息的对象shelf和一个包含图像文件扩展名的列表extensions,使用is_image函数检查该路径对应的文件是否为图像文件(需要传入路径和扩展名列表),若为图像文件则使用add_path函数将其添加到shelf中。这里假设
is_image
和
add_path
函数已经在其他地方定义好了。
is_image
add_path
import os
def process_path(path, shelf, extensions):
if is_image(path, extensions):
add_path(path, shelf)
这里假设
is_image
和
add_path
函数已经在其他地方定义好了,
extensions
是一个包含图像文件扩展名的列表,
shelf
是用于存储文件信息的对象。
81、对象(object)和实例(instance)之间有什么区别?
`class object` 指的是代表一个类的对象,它是类定义的结果;而 `instance` 是属于一个类的对象,`instantiation` 是创建属于某个类的对象的过程。简单来说,对象是一个更宽泛的概念,而实例是特定类的具体对象,是对象在类这个范畴下的具体体现。一个实例必然是一个对象,但一个对象不一定是某个类的实例。
82、在Python的f-string中可以使用哪些格式说明符?
在Python的f-string中可以使用如
02d
这样的格式说明符。例如:
f'{lunch.hour:02d}:{lunch.minute:02d}:{lunch.second:02d}'
其中
02d
表示该整数至少显示两位数字,若不足两位则在前面补零。
83、编写一个名为subtract_time的函数,该函数接受两个Time对象,并返回它们之间的时间间隔(以秒为单位),假设它们是同一天内的两个时间。
class Time:
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second
def time_to_int(time):
minutes = time.hour * 60 + time.minute
seconds = minutes * 60 + time.second
return seconds
def subtract_time(t1, t2):
return abs(time_to_int(t1) - time_to_int(t2))
84、编写一个名为is_after的函数,该函数接受两个Time对象,如果第二个时间在当天晚于第一个时间,则返回True,否则返回False。
以下是实现该功能的Python代码:
class Time:
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second
def time_to_int(self):
return self.hour * 3600 + self.minute * 60 + self.second
def is_after(t1, t2):
return t1.time_to_int() < t2.time_to_int()
你可以使用以下方式调用这个函数:
t1 = Time(10, 30, 0)
t2 = Time(12, 0, 0)
print(is_after(t1, t2)) # 输出 True
85、1. 编写一个名为 make_date 的函数,该函数接受年、月和日作为参数,创建一个 Date 对象,将参数赋值给对象的属性,并返回新对象。创建一个表示 1933 年 6 月 22 日的对象。2. 编写一个名为 print_date 的函数,该函数接受一个 Date 对象,使用 f 字符串格式化对象的属性并打印结果。如果你用创建的 Date 对象进行测试,结果应该是 1933 – 06 – 22。3. 编写一个名为 is_after 的函数,该函数接受两个 Date 对象作为参数,如果第一个日期在第二个日期之后,则返回 True。创建一个表示 1933 年 9 月 17 日的第二个对象,并检查它是否在第一个对象之后。
class Date:
pass
def make_date(year, month, day):
date = Date()
date.year = year
date.month = month
date.day = day
return date
# 创建一个表示 1933 年 6 月 22 日的对象
date1 = make_date(1933, 6, 22)
def print_date(date):
print(f'{date.year:04d}-{date.month:02d}-{date.day:02d}')
# 测试 print_date 函数
print_date(date1)
def is_after(date1, date2):
if date1.year > date2.year:
return True
elif date1.year == date2.year:
if date1.month > date2.month:
return True
elif date1.month == date2.month:
return date1.day > date2.day
return False
# 创建一个表示 1933 年 9 月 17 日的对象
date2 = make_date(1933, 9, 17)
# 检查 date2 是否在 date1 之后
print(is_after(date2, date1))
86、想要获取更多关于静态方法的信息,可以向虚拟助手提问:‘实例方法和静态方法有什么区别?’
在编程中,实例方法和静态方法有以下区别:
实例方法
必须通过类的实例对象来调用。
可以访问和修改实例的属性。
在定义时第一个参数通常是
self
,用于引用调用该方法的实例对象。
静态方法
可以直接通过类名调用,不需要创建类的实例。
它不能访问或修改实例的属性。
在定义时不需要
self
参数,通常使用
@staticmethod
装饰器来标识。
87、让虚拟助手生成一个静态方法,生成结果可能有什么特征?
让虚拟助手生成静态方法时,结果可能以 `@staticmethod` 开头。若对装饰器感兴趣,可向虚拟助手进一步了解。