Skip to content
📌知识点小结
  • 函数是“打包好、可重复调用的一段逻辑”,用 def 定义。
  • 函数可接收参数(输入),用 return 返回结果(输出)。
  • 定义不会执行,调用(函数名加括号)才执行。
  • 函数让代码复用、结构清晰、便于分工和测试。
  • 安全脚本常把“检测单个目标”封装成函数,再用循环对多个目标调用。
✅自测一下

0.29 函数:把逻辑打包复用 ​

第〇篇【零基础预科】免费。当一段操作要反复用,就把它做成函数。

前两篇里,条件判断和循环让你能写"一段会分叉、会重复"的代码;函数则让你把这一段代码打包、起个名字、随时喊它。到这一篇,你手里就凑齐了写检测脚本最核心的三块积木:条件、循环、函数。

一、定义与调用 ​

python
def greet(name):          # 定义:参数 name
    print("你好,", name)

greet("eason")            # 调用:传入 "eason"
greet("tom")              # 再调用,复用同一段逻辑
  • def 声明函数,括号里是参数(输入);
  • 定义时不执行,只有调用(名字 + 括号)才执行缩进块。

greet("eason") 和 greet("tom") 跑的是同一段代码,只是塞进去的名字不同。这就像一台榨汁机:结构固定,你丢苹果进去出苹果汁、丢橙子进去出橙汁。函数体是机器,参数是你丢进去的原料,def 只是把机器装好放在那儿,你不按开关(调用),它自己不会转。

你可能会问:我明明写了 def greet(...),为什么运行后什么都没打印? 因为 def 那一行只是"定义"——它告诉 Python"有这么个函数",并不执行。你必须再写一句 greet("eason") 真正去调用它,机器才转。新手最常犯的错就是"只定义、忘了调用",然后盯着屏幕纳闷"代码呢"。看到没反应,先检查函数名后面到底有没有加括号调用。

函数名最好起得"见名知意"。greet 一看就知道在打招呼,is_vulnerable 一看就知道在判断"是否有漏洞"——名字本身就是注释。别图省事起成 a、func1、test,过三天你自己都忘了它干嘛。这个习惯现在养,后面读自己半年前写的脚本时会谢自己。

二、返回值:return ​

python
def add(a, b):
    return a + b          # 把结果交回

result = add(3, 5)        # result = 8
print(result)
  • return 把函数产出的结果返回,调用处可接收;
  • 没有 return 的函数返回 None;
  • 执行到 return 立即结束函数。

print 和 return 的区别,是这里最该搞清的一对。print 只是把结果显示在屏幕上给你看,看完就没了,别的代码拿不到;return 才是真把结果"交回"给调用处,你能拿它存进变量、继续往下算。比如 add(3,5) 如果只是在函数里 print(8),外面写 result = add(3,5) 会发现 result 是空的(None),因为它根本没把 8 交出来。想让结果能被复用,就得用 return。

None 这个词先混个眼熟:它表示"什么都没有/空"。一个函数没写 return,调用它就默默返回 None,不报错——但你一拿它去做运算,就会报错。知道有这个东西,第一次碰到 TypeError: unsupported operand... None 时不会完全懵。

三、为什么要用函数 ​

  1. 复用:写一次,到处调用;
  2. 清晰:用函数名概括一段操作(如 check_vuln(url)),主流程像在读步骤;
  3. 易维护:改逻辑只改函数一处;
  4. 易测试:给定输入、检查输出是否正确。

这四点值得各举一个真实感受。"复用"最直接:你写好了一段发请求、判特征的代码,后面十个目标都要用,复制十遍太蠢,封成函数调用十次就行。"清晰"体现在读代码上——主流程里你看到 is_vulnerable(url),根本不用关心它内部怎么实现,光看名字就知道"它在查这个网址有没有漏洞";如果不封函数,主流程里直接摊着几十行发请求、取响应、查字符串的细节,你读三步就被绕晕了。

"易维护"是事后才懂的痛:特征串要从 rmi:// 换成别的,散在十处就得改十次,还容易漏改一处;封在函数里,改一处全生效。"易测试"则让排错变简单:怀疑检测逻辑有问题,不用跑整个批量,单独喂它一个已知有漏洞的地址、一个正常地址,看返回对不对,立刻能定位是逻辑错了还是网络问题。这四条合起来就是一句话:函数让长代码变得像拼积木,而不是一团乱麻。

四、安全脚本里的函数 ​

python
def is_vulnerable(url):
    # response = requests.get(url, timeout=5)
    # return "特征" in response.text
    return False

targets = ["http://a.com", "http://b.com"]
for url in targets:
    if is_vulnerable(url):       # 对每个目标调用检测函数
        print(url, "可能存在漏洞")

这是非常典型的结构:把"检测单个目标"写成函数,再用循环对多个目标调用。

你体会一下这个拆分:0.28 的循环负责"一个个轮流来",函数负责"对单个目标怎么查"。两者各管一件事——循环管重复,函数管逻辑。这样写的好处立刻显现:哪天你要升级检测逻辑(比如多加一个特征判断),只改 is_vulnerable 这一个函数,循环那边一行都不用动;想单独测某个目标行不行,直接 is_vulnerable("http://test.local") 就能调,不用跑整个批量。这就是"分而治之"在代码里的样子。

五、常见问题 ​

  • 定义后忘记调用 → 没反应;
  • 调用时参数个数对不上 → TypeError;
  • 函数内想改外部变量需注意作用域(初学时多用参数传入、return 返回)。

第二条看看真实报错长什么样:def add(a, b) 需要两个参数,你只写 add(3),运行就报 TypeError: add() missing 1 required positional argument: 'b'——翻译过来就是"add 还缺一个叫 b 的参数没给"。报错本身会告诉你缺哪个,照着补就行。第三条先不深究,你只要养成习惯:要给函数什么,用参数传进去;函数干完想留什么,用 return 交出来,就基本不会踩作用域的坑。等你真需要在函数里改外部变量了,再回头查"作用域"也不迟。

六、本篇小结 ​

  • 函数用 def 定义、可接参数、用 return 返回结果。
  • 定义不执行,调用(加括号)才执行。
  • 函数带来复用、清晰、易维护和易测试。
  • 安全脚本:检测单目标写成函数,循环批量调用。

到这里,条件、循环、函数三块积木你都齐了。别小看它们——后面所有检测脚本,都是这三样的排列组合。

下一篇 0.30 解释"解释型"和"编译型"语言的区别。