背景

研究《langchain-ChatGLM》项目的过程中,发现一个比较神奇的写法,可能还是我自己见识太少,以后还是得多看各种大佬写的源码。

大佬的源码

1
2
3
4
5
6
7
def similarity_search_with_score_by_vector(
self, embedding: List[float], k: int = 4
) -> List[Tuple[Document, float]]:
pass

# 第一次看到这样修改类的方法
FAISS.similarity_search_with_score_by_vector = similarity_search_with_score_by_vector

在之前的思维中一般写法都是先继承这个类,然后再重新写一下这个函数,不知道python原来可以直接动态修改类方法。

实操

总结下来主要就是三种

  1. 直接继承一个类,然后重写这个函数
  2. 用上面讲到的方法动态修改
  3. 也可以用setattr魔法函数动态修改类的属性和方法

话不多说,上Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Student:
def __init__(self, name):
self.name = name

def self_introduce(self):
print(f'I am {self.name}.')

class NewStudent(Student):
def __init__(self,name):
super(NewStudent, self).__init__(name)
self.name=name

def self_introduce(self):
print(f'My name is {self.name}1. Nice to meet you!')

def new_self_introduce(self):
print(f'My name is {self.name}2. Nice to meet you!')


def set_self_introduce(self):
print(f'My name is {self.name}3. Nice to meet you!')

a = Student('xiaoming')
a.self_introduce()

# 第一种方法

n = NewStudent('xiaoming')
n.self_introduce()

# 第二种种方法
Student.self_introduce = new_self_introduce
a.self_introduce()

# 第三种方法
setattr(Student,"self_introduce",set_self_introduce)
a.self_introduce()

b = Student('xiaohong')
b.self_introduce()

结论

  • 如果不是说要重复调用一个类的新方法,直接用setattr或者直接替换对象的方式,可以说简单高效
  • 如果说一个类的新方法要被多方调用,可以考虑用继承的方法,当然可读性也会高一些