4、Python基础速通(下):函数、类与模块化编程,理解LangChain的底层逻辑。
好,咱们接着聊。上一节我们把Python的“手脚”给练活了,这一节要动真格的了——函数、类、模块化。说白了,这就是你从“写脚本”到“写系统”的必经之路。
我当年刚入行时,觉得能写个几百行的脚本就挺牛了。后来接手一个项目,代码堆了三千行,改一个bug要翻十分钟……嗯,从那以后,我彻底理解了什么叫“代码组织”。
你想想看,LangChain那么复杂的框架,底层不就是靠这些基础概念堆起来的吗?今天我们就把它扒开看看。
4.1 函数:把你的逻辑装进“黑盒子”
函数是什么?说白了,就是把一段重复用的代码打包,起个名字。以后想用,喊它一声就行。
我个人习惯,只要一段逻辑出现两次以上,立马写成函数。别偷懒,这是职业素养。
4.1.1 定义与调用
def greet(name):
return f"你好,{name}!"
print(greet("小明")) # 输出:你好,小明!
这里有个小细节:def 后面要加冒号,函数体要缩进。我见过太多新手在这里栽跟头。
4.1.2 参数与返回值
函数可以接收参数,也可以返回结果。参数可以有默认值,这样调用时更灵活。
def create_prompt(template, temperature=0.7):
return {"prompt": template, "temp": temperature}
# 两种调用方式
print(create_prompt("讲个笑话"))
print(create_prompt("写首诗", temperature=0.9))
4.2 类:把数据和操作绑在一起
类,是面向对象编程的核心。你想想看,LangChain里的LLM、Chain、Agent,哪个不是类?
类把“属性”(数据)和“方法”(操作)封装在一起。这就像一台咖啡机——你不需要知道内部怎么加热、怎么研磨,你只需要按按钮就行。
4.2.1 定义一个简单的类
class LLM:
def __init__(self, model_name, api_key):
self.model_name = model_name
self.api_key = api_key
def generate(self, prompt):
# 假装调用了API
return f"[{self.model_name}] 回复:{prompt}"
# 使用
my_llm = LLM("gpt-3.5", "sk-xxx")
print(my_llm.generate("你好"))
__init__ 是构造方法,创建对象时自动调用。self 指向实例本身。记住,类里所有方法第一个参数都是 self。
4.2.2 继承:站在巨人的肩膀上
继承是面向对象的一大杀器。你可以基于一个父类,扩展出子类,复用代码。
class BaseLLM:
def __init__(self, model_name):
self.model_name = model_name
def generate(self, prompt):
raise NotImplementedError("子类必须实现此方法")
class OpenAILLM(BaseLLM):
def generate(self, prompt):
return f"OpenAI {self.model_name} 生成:{prompt}"
class LocalLLM(BaseLLM):
def generate(self, prompt):
return f"本地模型 {self.model_name} 生成:{prompt}"
4.3 模块化编程:别把所有鸡蛋放一个篮子里
模块化,就是把代码拆成多个文件。每个文件负责一块功能。我见过最糟糕的项目,一个文件一万行……维护起来简直想哭。
4.3.1 创建模块
假设我们有一个项目结构:
my_project/
├── main.py
├── utils.py
└── models/
├── __init__.py
└── llm.py
__init__.py 告诉Python这个文件夹是一个包。可以是空文件。
4.3.2 导入模块
# main.py
from utils import format_prompt
from models.llm import OpenAILLM
llm = OpenAILLM("gpt-4")
prompt = format_prompt("你好")
print(llm.generate(prompt))
4.4 理解LangChain的底层逻辑
好了,现在我们把前面的知识串起来。LangChain本质上就是一套“组件化”的框架。它的核心逻辑可以用几句话概括:
- 组件化:每个功能(LLM调用、Prompt管理、输出解析)都是一个独立的类。
- 链式调用:通过Chain把这些组件串起来,前一个的输出是后一个的输入。
- 可扩展:你只要实现基类定义的接口,就能接入自己的模型或逻辑。
举个例子,一个简单的LangChain调用,底层大概是这样:
class PromptTemplate:
def __init__(self, template):
self.template = template
def format(self, **kwargs):
return self.template.format(**kwargs)
class LLMChain:
def __init__(self, llm, prompt_template):
self.llm = llm
self.prompt_template = prompt_template
def run(self, **kwargs):
prompt = self.prompt_template.format(**kwargs)
return self.llm.generate(prompt)
# 使用
prompt = PromptTemplate("请用{style}风格写一首关于{subject}的诗")
llm = OpenAILLM("gpt-4")
chain = LLMChain(llm, prompt)
result = chain.run(style="古风", subject="月亮")
print(result)
看到了吗?这就是函数、类、模块化编程的实战应用。你写的每一个类,每一个函数,都在为这种“链式思维”打基础。
最后说一句:编程基础就像盖楼的地基。地基打得深,楼才能盖得高。别急着追新框架,先把Python这几板斧练扎实了。后面学LangChain、Agent、RAG,你会觉得“哦,原来就这么回事”。