在看书里的代码时了解了一个python的语法知识,是有关class类的。
代码如下:
class Vocab: #@save"""文本词表"""def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):if tokens is None:tokens = []if reserved_tokens is None:reserved_tokens = []# 按出现频率排序counter = count_corpus(tokens)self._token_freqs = sorted(counter.items(), key=lambda x: x[1],reverse=True)# 未知词元的索引为0self.idx_to_token = ['<unk>'] + reserved_tokensself.token_to_idx = {token: idxfor idx, token in enumerate(self.idx_to_token)}for token, freq in self._token_freqs:if freq < min_freq:breakif token not in self.token_to_idx:self.idx_to_token.append(token)self.token_to_idx[token] = len(self.idx_to_token) - 1def __len__(self):return len(self.idx_to_token)def __getitem__(self, tokens):if not isinstance(tokens, (list, tuple)):return self.token_to_idx.get(tokens, self.unk)return [self.__getitem__(token) for token in tokens]def to_tokens(self, indices):if not isinstance(indices, (list, tuple)):return self.idx_to_token[indices]return [self.idx_to_token[index] for index in indices]@propertydef unk(self): # 未知词元的索引为0return 0@propertydef token_freqs(self):return self._token_freqsdef count_corpus(tokens): #@save"""统计词元的频率"""# 这里的tokens是1D列表或2D列表if len(tokens) == 0 or isinstance(tokens[0], list):# 将词元列表展平成一个列表tokens = [token for line in tokens for token in line]return collections.Counter(tokens)
看的时候不太明白__len__和__getitem__这些为什么要在前后加两个下划线,之前了解过__call__是默认调用函数,比如nn.Module的默认调用函数是forward,也就是继承了nn.Module后的class中的forward函数是默认调用函数,“类名(X)”这个语法执行的就是默认调用函数。
还有__init__初始化函数,在初始化类是,使用“类名=类(xxx)”调用初始化函数创建新类。
这里又认识到了几个“特殊方法”,就是与默认调用函数和初始化函数相似的python的预定义方法,在某些特定情况下,这些函数会被自动调用。
一、__str__和__repr__
__str__和__repr__是用于定义对象的字符串表现形式
比如:
class People:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f"姓名:{self.name}, 年龄:{self.age}"p = People('小y', '19')
print(p)
这时候返回的就是
因为调用了__str__函数,将类People当作一个字符串返回。
__repr__与之相似,不过它实现的应该是一个对开发者友好的函数。
class People:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f"姓名:{self.name}, 年龄:{self.age}"def __repr__(self):return f"People:{self.name}, {self.age}"p = People('小y', '19')
print(p)
print(repr(p))
二、__len__
函数可以返回类中某个串的长度,以便可以之间调用"len(类名)",表示类中长度的概念。
三、__getitem__
函数可以返回指定索引的元素,可以使用"类名[索引]"调用类中某个列表的某个元素。
还有@property这个方法,可以将函数变为一个属性,调用函数时直接将函数视作属性。
比如:
class People:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f"姓名:{self.name}, 年龄:{self.age}"@propertydef _age(self):return self.age@_age.setterdef _age(self, new_age):if(new_age < 0):raise ValueError("值不能为负")else:self.age = new_agep = People('小y', '19')
print(p)
print(p._age)
p._age = 20
print(p)