Python程序设计 函数

简单函数

函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。

函数的使用包含两个步骤:

  1. 定义函数 —— 封装 独立的功能

  2. 调用函数 —— 享受 封装 的成果

函数的作用,在开发程序时,使用函数可以提高编写的效率以及代码的重用

函数的定义

声明函数

  1. def :表示函数的关键字,是英文 define 的缩写

  2. 函数名:函数的名称,后续根据函数名调用函数,函数名称应该能够表达函数封装代码的功能

  3. arg : 即 argument 参数

  4. 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...

  5. 函数名称的命名应该符合标识符的命名规则

    • 可以由 字母、下划线和数字组成

    • 不能以数字开头

    • 不能与关键字重名

# 声明函数
def func():
    # 函数体代码
    # 函数体代码
    # 函数体代码
    # 函数体代码
    print()

def 是声明函数的关键字,必须小写

由于函数一般是为了实现某个功能才定义的, 所以通常我们将函数名命名为动词,比如 get_sum

调用函数

# 调用函数
函数名();  # 通过调用函数名来执行函数体代码

调用的时候千万不要忘记添加小括号

口诀:函数不调用,自己不执行

注意:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。

函数的封装

函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口

简单理解:封装类似于将电脑配件整合组装到机箱中 ( 类似快递打包)

例子:封装计算1-100累加和

""" 
   计算1-100之间值的函数
"""


# 声明函数
def get_sum():
    total = 0
    for i in range(100):
        total += i
    print(total)


# 调用函数
get_sum()

例子:利用函数 求两个数的最大值

# 利用函数 求两个数的最大值
def get_max(num1, num2):
    if num1 > num2:
        print(num1)
    else:
        print(num2)


get_max(1, 3)
get_max(11, 3)

调用函数很简单的,通过 函数名() 即可完成对函数的调用

细节问题

能否将函数调用放在函数定义的上方?

  • 不能

  • 因为在使用函数名调用函数之前,必须要保证 Python 已经知道函数的存在

  • 否则控制台会提示 NameError: name 'f' is not defined (名称错误:f这个名字没有被定义)

函数的功能

有两个变量 xy ,当 x 取其变化范围中的每一个特定值时,相应地有唯一的 y 与它对应,则称 yx 的函数。记为 y = fx ),其中 x 为自变量, y 为因变量。

  1. y = kx + b 封装成一个函数,其中 k=5 , b=6 , 假设 x=5

  2. 在函数下方调用线性方程函数,打印结果

"""
# 函数在数学组的表达形式
y = f(x)
y = kx + b
"""
k = 5
b = 6


# define 定义
# f 为函数名
def f(x):
    # 里面的内容是函数体,函数执行的代码
    y = k * x + b
    # return 函数的返回值
    return y

参数可变

我们定义和调用一个没有参数的函数。假设需要求当 x 分别为 56 时,f(x) 的结果相加:

x = 5

def f(x):

    y = 5 * x + 6
    return y


print(f(5) + f(6))

多次调用产生不同的结果

带参数的函数有一个非常大的好处,通过修改调用函数传入的参数,从而得到不同的值。

def f(x):

    y = 5 * x + 6
    return y


f(5)
f(6)
f(7)

函数的返回值

建立在之前的函数之上,如果想得到函数的计算结果,然后相加在进行输出改如何处理?例如在函数外部将函数 f 的结果加 10 再进行输出。

函数的返回值

函数是一个功能块,该功能到底执行成功与否,需要通过返回值来告知调用者。

x = 5

def f():
    
    y = 5 * x + 6
    # return 关键字 返回一个内容
    return y
    
print(f() +y)

程序运行到所遇到的第一个return即返回(退出def块),实现函数值的返回,不会再运行第二个return。返回时可附带一个返回值,由return后面的参数指定。

return 之后函数就结束了,不会再执行后续代码

案例:

编写一个函数,求1+2+3+...+n

  1. 定义一个函数

  2. 函数接收一个参数 n

  3. 对1到n的数求和

  4. 打印和

def sum_test(n):
    sum  = 0
    for x in range(1,n+1):
        sum += x
    return sum

print(sum_test(10))
'''
55
'''

函数的其他形式

函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形式

  1. 无参数,无返回值

  2. 无参数,有返回值

  3. 有参数,无返回值

  4. 有参数,有返回值

案例:函数复用

"""
复利公式:s = p(1 + i)^n

余额宝 兴全添利宝 年化 2.5610%
假设本金(principal)10000
1、请问分别存 5年 10年 15年 20年后 本金利息共多少
2、如果利率(interest)变成 6% 分别存 5年 10年 15年 20年后 本金利息共多少
3、如果本金变成 20000,利率不变 分别存 5年 10年 15年 20年后 本金利息共多少
"""


def func(p, i, n):
    s = p * (1 + i) ** n
    return s

函数的参数

位置参数

Python 处理参数的方式要比其他语言更加灵活。其中,最熟悉的参数类型是位置参数,传入参数的值是按照顺序依次复制过去的。下面创建一个带有位置参数的函数:

需求:

y = k * x +bkb 也不固定。

def f(x, k, b):
    y = k * x + b
    print(y)


f(5, 5, 6)

尽管这种方式很常见,但是位置参数的一个弊端是必须熟记每个位置的参数的含义。在调用函数 f() 时误把最后一个参数当作第一个参数,会得到完全不同的结果:

def f(x, k, b):
    print("x:{} k:{} b:{}".format(x, k, b))
    y = k * x + b
    return(y)


f(5, 5, 6)

关键字参数

为了避免位置参数带来的混乱,调用参数时可以指定对应参数的名字,甚至可以采用与函数定义不同的顺序调用:

def f(x, k, b):
    print("x:{} k:{} b:{}".format(x, k, b))
    y = k * x + b
    return(y)

f(x=5, k=5, b=6)

你也可以把位置参数和关键字参数混合起来。首先,实例化参数 ,然后对参数使用关键字参数的方式:

def f(x, k, b):
    print("x:{} k:{} b:{}".format(x, k, b))
    y = k * x + b
    return(y)

f(5, k=5, b=6)

如果同时出现两种参数形式,首先应该考虑的是位置参数。

默认参数

当调用方没有提供对应的参数值时,你可以指定默认参数值。这个听起来很普通的特性实际上特别有用,以之前的例子为例:

def f(x, k=5, b=6):
    print("x:{} k:{} b:{}".format(x, k, b))
    y = k * x + b
    return y


f(x=5, k=5, b=6)

不确定长度的参数

*args

收集位置参数(了解)

在不清楚传入参数是多少个

# 用 * 收集位置参数
# int * 特殊符号 有特殊的作用, 在定义函数的括号里面,用于收集所有的位置参数
# 在输出 或者是运行代码的过程中 是解包 包:元组、列表、迭代器、生成器
def print_args(*args):
    # * 解包的标志
    print('位置参数的类型:', type(args))
    print('位置参数的内容:', args)

无参数调用函数,则什么也不会返回:

>>> print_args()
print_args ()

给函数传入的所有参数都会以元组的形式返回输出:

>>> print_args(3, 2, 1, 'wait!', 'uh...')
 (3, 2, 1, 'wait!', 'uh...')

这样的技巧对于编写像 print() 一样接受可变数量的参数的函数是非常有用的。如果你函数同时有限定的位置参数,那么 *args 会收集剩下的参数:

>>> def print_args1(arg1, arg2, *args):
...     print('arg1:', arg1)
...     print('arg2:', arg2)
...     print('args:', args)
...
>>> print_args1(1,2,3,4,5,6)
arg1: 1
arg2: 2
args: (3, 4, 5, 6)

当使用 * 时不需要调用元组参数 args,不过这也是 Python 的一个常见做法。

**kwargs

收集关键字参数

使用两个星号可以将参数收集到一个字典中,参数的名字是字典的键,对应参数的值是字典的值。下面的例子定义了函数 print_kwargs(),然后打印输出它的关键字参数:

def print_kwargs(*arg, **kwargs):
    """ args为关键字元组  kwargs为双元关键字元组 """
    print('位置参数:', arg)
    print('关键字参数:', kwargs)

例子

案例:假设 python 中的 print 不能一次性传入多个参数使用了,让我们自己实现 print 可以传递多个参数的功能。

# 假设 print 函数突然变成了一下这个样子
def print_(arg):
    print(arg, sep="", end="")

要求:自己编写一个 changed_print 函数实现原本 print 的功能。

例:原本函数的功能

In [1]: print(1)
1

In [2]: print(1, 2, 3, 4)
1 2 3 4

In [3]: print(1, 2, 3,4, sep=',')
1,2,3,4

In [4]: print(1, 2, 3,4, sep=',', end='我是结尾')
1,2,3,4我是结尾
def changed_print(*args, sep=' ', end='\n'):
    # print_ 只能接受一个参数
    for arg in args[:-1]:
        print_1(arg)
        # , 空格 #
        print_1(sep)

    print(args[-1])
    print_1('\n')

一等公民函数

在 Python 中,函数是一等对象。编程语言理论家把“一等对象”定义为满足下述条件的程序实体:

  • 在运行时创建

  • 能赋值给变量或数据结构中的元素

  • 能作为参数传给函数

  • 能作为函数的返回结果

在 Python 中,整数、字符串和字典都是一等对象——没什么特别的。接下来的内容将重点讨论把函数作为对象的影响和实际应用。

比如说我要将之前函数修改一个名字,使用新的函数名去调用旧的函数

def f(x):
    
    y = 5 * x + 6
    # return 关键字 返回一个内容
    return y

d = f

print(d(x) +d(y))

把函数当参数传递

案例需求 f(1) + f(2) + f(3) + f(4) + f(5)

print(f(1) + f(2) + f(3) + f(4) + f(5))

# 把函数当参数传递
print(f(f(1)))

设:求 f(1) + f(2) + f(3) + f(4) + f(5) + ...+f(N)

def sum_(N):
    total = 0
    for i in range(1, N + 1):
        total += f(N)
    return total

print_(sum_(5))

全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。

交换变量值

需求:有变量a = 10b = 20,交换两个变量的值。

  • 方法一

借助第三变量存储数据。

# 1. 定义中间变量
c = 0

# 2. 将a的数据存储到c
c = a

# 3. 将b的数据20赋值到a,此时a = 20
a = b

# 4. 将之前c的数据10赋值到b,此时b = 10
b = c

print(a)  # 20
print(b)  # 10
  • 方法二
a, b = 1, 2
a, b = b, a
print(a)  # 2
print(b)  # 1

例子

冒泡排序(冒泡排序)也是一种简单的简单列访问排序。它重复地走过去要排序的数,一次比较两个元素,如果他们的顺序错误让他们交换过来。走访数工作列的是重复地进行到那时已经没有再需要交换了,该算法的名字会因为越过元素会来交换慢慢地“浮”到数列的排序。

需求: 任意给定一组序列数字, 比如 [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48], 将序列从小到大排列。(不能使用python函数解决)

"""
		需求: 任意给定一组序列数字,
		比如 [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48],
		将序列从小到大排列。(不能使用python函数解决)
"""

def bubbleSort(arr): 
    n = len(arr) 
    for i in range(n): 
        for j in range(0, n - 1): 
            if arr[j] > arr[j + 1]: 
                arr[j], arr[j + 1] = arr[j + 1], arr[j]

    return arr

print(bubbleSort([3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]))
# 结果:[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

递归

递归的应用场景

递归是一种编程思想,应用场景:

  1. 在我们日常开发中,如果要遍历一个文件夹下面所有的文件,通常会使用递归来实现;

  2. 在后续的算法课程中,很多算法都离不开递归,例如:快速排序。

递归的特点

  • 函数内部自己调用自己

  • 必须有出口

应用:数字累加求和

  • 代码

# 3 + 2 + 1
def sum_numbers(num):
    if num == 1:
        return 1
    return num + sum_numbers(num-1)


sum_result = sum_numbers(3)
# 输出结果为6
print(sum_result)
  • 执行结果

lambda 表达式

lambda 的应用场景

如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda 简化。

lambda语法

lambda 参数列表 : 表达式

注意

  • lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。

  • lambda表达式能接收任何数量的参数但只能返回一个表达式的值。

快速入门

# 函数
def fn1():
    return 200


print(fn1)
print(fn1())


# lambda表达式
fn2 = lambda: 100
print(fn2)
print(fn2())

注意:直接打印lambda表达式,输出的是此lambda的内存地址

示例:计算a + b

函数实现

def add(a, b):
    return a + b


result = add(1, 2)
print(result)

思考:需求简单,是否代码多?

lambda实现

fn1 = lambda a, b: a + b
print(fn1(1, 2))

lambda的参数形式

无参数

fn1 = lambda: 100
print(fn1())

一个参数

fn1 = lambda a: a
print(fn1('hello world'))

默认参数

fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))

可变参数:*args

fn1 = lambda *args: args
print(fn1(10, 20, 30))

注意:这里的可变参数传入到lambda之后,返回值为元组。

可变参数:**kwargs

fn1 = lambda **kwargs: kwargs
print(fn1(name='python', age=20))

lambda的应用

带判断的lambda

fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))

列表数据按字典key的值排序

students = [
    {'name': 'TOM', 'age': 20},
    {'name': 'ROSE', 'age': 19},
    {'name': 'Jack', 'age': 22}
]

# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)

# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)

# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)

高阶函数

把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。

体验高阶函数

在Python中,abs()函数可以完成对数字求绝对值计算。

abs(-10)  # 10

round()函数可以完成对数字的四舍五入计算。

round(1.2)  # 1
round(1.9)  # 2

需求:任意两个数字,按照指定要求整理数字后再进行求和计算。

  • 方法1

def add_num(a, b):
    return abs(a) + abs(b)


result = add_num(-1, 2)
print(result)  # 3
  • 方法2
def sum_num(a, b, f):
    return f(a) + f(b)


result = sum_num(-1, 2, abs)
print(result)  # 3

注意:两种方法对比之后,发现,方法2的代码会更加简洁,函数灵活性更高。

函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。

内置高阶函数

map()

map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。

需求:计算list1序列中各个数字的2次方。

list1 = [1, 2, 3, 4, 5]


def func(x):
    return x ** 2


result = map(func, list1)

print(result)  # <map object at 0x0000013769653198>
print(list(result))  # [1, 4, 9, 16, 25]

zip()

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同

a = [1,2,3]
b = [4,5,6]
c = [4,5,6,7,8]

result = zip(a,b)  # 打包为元组的列表
# 结果:[(1, 4), (2, 5), (3, 6)]

result = zip(a,c)  # 元素个数与最短的列表一致
# 结果:[(1, 4), (2, 5), (3, 6)]

reduce()

reduce() 函数会对参数序列中元素进行累积。

reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。

注意:reduce()传入的参数func必须接收2个参数。

需求:计算list1序列中各个数字的累加和。

import functools

list1 = [1, 2, 3, 4, 5]


def func(a, b):
    return a + b


result = functools.reduce(func, list1)

print(result)  # 15

filter()

filter(func, lst)函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象。如果要转换为列表, 可以使用 list() 来转换。

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


def func(x):
    return x % 2 == 0


result = filter(func, list1)

print(result)  # <filter object at 0x0000017AF9DC3198>
print(list(result))  # [2, 4, 6, 8, 10]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/373017.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity3d Shader篇(一)— 顶点漫反射着色器解析

文章目录 前言一、顶点漫反射着色器是什么&#xff1f;1. 顶点漫反射着色器的工作原理 二、编写顶点漫反射着色器1. 定义属性2. 创建 SubShader3. 编写着色器程序段4. 完成顶点着色器5. 完成片段着色器 三、效果四、总结 前言 在 Unity 中&#xff0c;Shader 可以用来实现各种…

jmeter设置关联

一、为什么要设置关联&#xff1f; http协议本身是无状态的&#xff0c;客户端只需要简单向服务器请求下载某些文件&#xff0c;无论是客户端还是服务端都不去记录彼此过去的行为&#xff0c;每一次请求之间都是独立的。如果jmeter需要设置跨线程组脚本&#xff0c;就必须设置…

【问题篇】activiti工作流转办并处理备注问题

当处理activiti转办问题时&#xff0c;需要做的就是处理审批人和备注问题。 处理的思路是&#xff0c;先将当前环节标志成转办标签&#xff0c;再通过BUSINESS_KEY_找到流程实例的历史记录&#xff0c;找到最新的一条复制一份出来&#xff0c;表示需要转办到的人的历史记录并设…

APP专项测试方法总结

APP专项测试 1、网络测试 可使用抓包工具辅助网格测试推荐&#xff1a;fiddler&#xff0c;Charles 网络切换&#xff1a; 2G-3G-4G-wifi-网络信号差–无网 网络信号弱&#xff1a; 关注是否出现ANR、crash 2、中断测试 意外中断&#xff1a; 来电&#xff1b;短信&am…

不需英文基础也可以轻松学编程,中文编程开发工具免费版下载,编程工具构件箱之扩展控制面板构件用法

不需英文基础也可以轻松学编程&#xff0c;中文编程开发工具免费版下载&#xff0c;编程工具构件箱之扩展控制面板构件用法 一、前言 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例源码文件下载可以点击最下方官网卡片——软件下载——常…

ShardingSphere 5.x 系列【3】分库分表中间件技术选型

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 前言2. My Cat3. ShardingSphe…

C++ 类与对象(下)

目录 1. 再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit关键字 2. static成员 2.1 概念 2.2 特性 3.友元 3.1友元函数 3.2 友元类 4. 内部类 5.匿名对象 6.拷贝对象时的一些编译器优化 7. 再次理解类和对象 【本节目标】 1. 再谈构造函数 2. Static成员…

【产品升级】SmartPipe升级到版本2.0

在近一个月的攻关和测试下&#xff0c;SmartPipe软件轴线自动识别算法的性能大幅提升&#xff0c;鲁棒性和稳定性进一步增强。近一年来客户累计反馈的多种复杂管路&#xff08;包括带有支管管路、带有压瘪段管路、推弯管、装配管、带有复杂孔洞管路等&#xff09;现在均能够正确…

通过消息队列实现进程之间通信代码

#include <myhead.h> struct msgbuf {long int mtype; char mtext[1024]; }; //定义一个消息大小 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long int) int main(int argc, const char *argv[]) {//1、创建key值以便创建消息队列key_t key ftok("/", k)…

Bootstrap5 图片轮播

Bootstrap5 轮播样式表使用的是CDN资源 <title>亚丁号</title><!-- 自定义样式表 --><link href"static/front/css/front.css" rel"stylesheet" /><!-- 新 Bootstrap5 核心 CSS 文件 --><link rel"stylesheet"…

STM32WLE5JC

Sub-GHz 无线电介绍 sub-GHz无线电是一种超低功耗sub-GHz无线电&#xff0c;工作在150-960MHz ISM频段。 在发送和接收中采用LoRa和&#xff08;G&#xff09;FSK调制&#xff0c;仅在发送中采用BPSK/(G)MSK调制&#xff0c;可以在距离、数据速率和功耗之间实现最佳权衡。 这…

freeswitch对接FunASR实时语音听写

1、镜像启动 通过下述命令拉取并启动FunASR软件包的docker镜像&#xff1a; sudo docker pull \registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-online-cpu-0.1.7 mkdir -p ./funasr-runtime-resources/models sudo docker run -p 10096:10095 -i…

【Gephi项目实战-带数据集】利用gephi绘制微博肖战超话120位用户关系图,并计算整体网络指标与节点指标

数据集在评论区&#xff0c;B站演示视频在评论区&#xff01; 简介 最近2天需要用到gephi做社会网络分析&#xff0c;于是从0开始接触gephi并摸索出了gephi的基本使用指南。下面将结合真实的节点文件与边文件&#xff0c;利用gephi绘制社会网络并计算相关测量指标。整个过程会…

我们都是宇宙的奇迹

我们都是独一无二的个体&#xff0c;是宇宙的奇迹 如果我不关注自我&#xff0c;那我在这个宏大的宇宙中有什么意义&#xff1f; 关于你的问题&#xff0c;我想没有一个简单的答案&#xff0c;因为不同的人可能有不同的看法和感受。有些人可能认为&#xff0c;如果不关注自我&…

jbdc的简单了解

JDBC JDBC所处的位置 JDBC的本质 Java操作数据库的一套接口。 补充 ddl:数据库定义语言,例如建表,创建数据库等。 dml:数据库操作语言,例如增删改。 dql:数据库查询语言,例如查询语句。 注意 在创建Java项目后的第一个步骤是导入jar包。 导入jar包的步骤 1 创建l…

【C语言】const修饰指针的不同作用

目录 const修饰变量 const修饰指针变量 ①不用const修饰 ②const放在*的左边 ③const放在*的右边 ④*的左右两边都有const 结论 const修饰变量 变量是可以修改的&#xff0c;如果把变量的地址交给⼀个指针变量&#xff0c;通过指针变量的也可以修改这个变量。 但…

TCP/IP详细介绍以及TCP/IP寻址

目录 ​编辑 1. TCP/IP 介绍 2. 计算机通信协议&#xff08;Computer Communication Protocol&#xff09; 3. 什么是 TCP/IP&#xff1f; 4. 在 TCP/IP 内部 5. TCP 使用固定的连接 6. IP 是无连接的 7. IP 路由器 8. TCP/IP 9. TCP/IP 寻址 10. IP地址 …

LeetCode、1137. 第 N 个泰波那契数【简单,动态规划】

文章目录 前言LeetCode、1137. 第 N 个泰波那契数【简单&#xff0c;动态规划】题目与分类思路一维动态规划 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术…

记录下ibus-libpinyin输入法的重新安装

目前的版本为: 首先把现在的ibus-libpinyin卸了 sudo apt-get --purge remove ibus-libpinyin sudo apt-get autoremove 安装教程请参考 Installation libpinyin/ibus-libpinyin Wiki GitHub yilai sudo apt install pkg-config sudo apt-get install libglib2.0-de…

02-Web应用_架构构建_漏洞_HTTP数据包_代理服务器

Web应用_架构构建_漏洞_HTTP数据包_代理服务器 一、网站搭建前置知识1.1 域名1.2、子域名1.3、DNS二、web应用环境架构类三、web应用安全漏洞分类四、web请求返回过程数据包 五、演示案例5.1、架构-Web应用搭建-域名源码解析5.2、请求包-新闻回帖点赞-重放数据包5.3、请求包-移…