高级写法
格式化字符串
- 使用f-strings(格式化字符串字面量): 这是从Python 3.6版本开始提供的最现代、最简洁的字符串格式化方法。你可以在字符串前加上’f’或’F’,并在花括号{}内嵌入表达式。
1 2 3 4 5
| name = "Alice" age = 30 formatted_string = f"我的名字是{name},我今年{age}岁。" print(formatted_string)
|
- 使用
.format()
方法: 这种方法允许你使用format()
方法的参数替换字符串中的占位符。
1 2 3 4 5
| name = "Bob" age = 25 formatted_string = "我的名字是{},我今年{}岁。".format(name, age) print(formatted_string)
|
- 使用
%
运算符(C风格的字符串格式化): 这种方法类似于C语言中的%
运算符,是一种较旧的字符串格式化方法。
1 2 3 4 5
| name = "Charlie" age = 35 formatted_string = "我的名字是%s,我今年%d岁。" % (name, age) print(formatted_string)
|
- 使用
str.format()
方法配合位置或命名占位符: 这种方法允许更灵活地控制参数的位置。
1 2 3 4 5 6 7 8 9 10
| name = "Eve" age = 40 formatted_string = "我的名字是{0},我今年{1}岁。".format(name, age) print(formatted_string)
formatted_string = "我的名字是{name},我今年{age}岁。".format(name=name, age=age) print(formatted_string)
|
- 使用
str.join()
方法: 这种方法用于将序列的元素用给定的字符串连接起来。
1 2 3 4
| fruits = ["苹果", "香蕉", "橙子"] formatted_string = "、".join(fruits) print(formatted_string)
|
根据你的喜好和Python版本选择合适的方法。一般来说,f-strings由于其可读性和效率而被推荐使用。
匿名函数
匿名函数是一种在Python中定义简单函数的方式,也被称为lambda函数。与普通函数(def定义的函数)不同,匿名函数不需要使用def关键字来定义,而是使用lambda关键字。匿名函数通常用于简单的功能或需要临时使用的小规模函数。
匿名函数的语法如下:
1
| lambda arguments: expression
|
- lambda:表示创建匿名函数的关键字。
- arguments:表示函数的参数列表。
- expression:表示函数的返回值。
使用说明:
- 匿名函数通常适用于简单的功能,不建议用于复杂逻辑的函数。
- 匿名函数返回一个函数对象,可以将其赋值给一个变量,也可以直接调用它。
实际使用举例: 下面我们将使用匿名函数来实现一些简单的功能。
- 计算两个数的和:
1 2 3
| add = lambda x, y: x + y result = add(5, 3) print(result)
|
- 判断一个数是否为偶数:
1 2 3
| is_even = lambda num: num % 2 == 0 print(is_even(10)) print(is_even(7))
|
- 对列表进行排序:
1 2 3
| fruits = ["apple", "orange", "banana", "grape"] fruits.sort(key=lambda fruit: len(fruit)) print(fruits)
|
- 使用map()函数对列表元素进行平方运算:
1 2 3
| numbers = [1, 2, 3, 4, 5] squared_numbers = list(map(lambda x: x**2, numbers)) print(squared_numbers)
|
- 在函数中使用匿名函数:
1 2 3 4
| def apply_operation(func, x, y): return func(x, y) result = apply_operation(lambda a, b: a * b, 3, 4) print(result)
|
请注意,在使用匿名函数时,要确保它们的功能简单且易于理解。
map方法
map()
是 Python 内置的函数之一,用于将一个函数(或其他可调用对象)应用于一个或多个序列(如列表、元组等)的每个元素,并将结果组成一个新的可迭代对象。它的基本语法如下:
1
| map(function, iterable, ...)
|
function
: 是一个函数或其他可调用对象,用于处理每个输入元素。
iterable
: 是一个或多个序列,可以是列表、元组、集合等。
map()
将会返回一个 map
对象,你可以将其转换成列表或其他类型的可迭代对象,如需要的话。
使用说明:
map()
接受一个或多个序列,它们的长度应该相同。如果传入多个序列,那么 function
将接受相同位置上的元素作为参数,这些元素组成一个元组传递给 function
。
map()
不会修改原始的输入序列,而是返回一个新的可迭代对象,其中包含了 function
处理后的结果。
实际使用举例: 下面我们通过几个例子来说明 map()
的用法。
- 将列表中的每个元素求平方:
1 2 3
| numbers = [1, 2, 3, 4, 5] squared_numbers = map(lambda x: x**2, numbers) print(list(squared_numbers))
|
- 将两个列表对应位置的元素相加:
1 2 3 4
| list1 = [1, 2, 3] list2 = [10, 20, 30] sum_result = map(lambda x, y: x + y, list1, list2) print(list(sum_result))
|
- 将字符串列表中的单词变为大写:
1 2 3
| words = ["hello", "world", "python"] upper_words = map(str.upper, words) print(list(upper_words))
|
- 使用
map()
转换多个序列:
1 2 3 4
| numbers = [1, 2, 3, 4, 5] squares = [1, 4, 9, 16, 25] addition = map(lambda x, y: x + y, numbers, squares) print(list(addition))
|
- 使用
map()
转换多个序列并取平均值:
1 2 3 4 5 6
| scores1 = [85, 90, 78] scores2 = [92, 88, 95] scores3 = [80, 85, 88]
average = map(lambda x, y, z: (x + y + z) / 3, scores1, scores2, scores3) print(list(average))
|
总结:map()
是一个很有用的函数,可以简化对序列元素的处理,并且能够在一行代码中完成一些常见的数据转换操作。
reduce方法
reduce()
是 Python 中 functools
模块提供的函数,用于对一个序列(如列表或元组)中的元素逐个进行合并处理,最终返回一个结果。它的基本语法如下:
1
| functools.reduce(function, iterable[, initializer])
|
function
: 是一个二元函数,接受两个参数,并返回一个结果。
iterable
: 是一个序列,可以是列表、元组、集合等。
initializer
(可选): 是初始值,如果提供了 initializer
,则会在处理序列元素之前将其作为初始值传递给 function
。
reduce()
在 Python 2 中是内置函数,但在 Python 3 中已经移至 functools
模块。所以在 Python 3 中使用 reduce()
需要先导入 functools
模块。
使用说明:
reduce()
首先将序列中的前两个元素传递给 function
,得到一个结果。
- 然后将上一步的结果和序列中的下一个元素传递给
function
,再得到一个结果。
- 依次类推,将每个元素和上一步的结果传递给
function
,直到处理完所有元素,得到最终结果。
实际使用举例: 下面我们通过几个例子来说明 reduce()
的用法。
- 计算列表中所有元素的累积乘积:
1 2 3 4
| from functools import reduce numbers = [1, 2, 3, 4, 5] product = reduce(lambda x, y: x * y, numbers) print(product)
|
- 使用初始值计算列表中所有元素的累积和:
1 2 3 4 5
| from functools import reduce numbers = [1, 2, 3, 4, 5] initial_value = 10 sum_result = reduce(lambda x, y: x + y, numbers, initial_value) print(sum_result)
|
- 将字符串列表中的单词拼接成一个句子:
1 2 3 4
| from functools import reduce words = ["Hello", "World", "Python"] sentence = reduce(lambda x, y: x + " " + y, words) print(sentence)
|
- 使用
reduce()
找到列表中的最大值:
1 2 3 4
| from functools import reduce numbers = [15, 32, 8, 20, 45] max_value = reduce(lambda x, y: x if x > y else y, numbers) print(max_value)
|
- 使用初始值计算列表中所有元素的平均值:
1 2 3 4 5
| from functools import reduce scores = [85, 90, 78, 92, 88] initial_value = 0 average = reduce(lambda x, y: x + y, scores, initial_value) / len(scores) print(average)
|
总结:reduce()
是一个强大的函数,可以用于处理多个元素之间的累积运算,但在 Python 3 中需要导入 functools
模块才能使用。在实际使用中,要确保传递给 reduce()
的函数符合合并运算的要求。
注意二者区别
map()
和 reduce()
是 Python 中两个用于处理序列的内置函数,它们都在 functools
模块中提供。
主要区别如下:
- 功能不同:
map()
:用于对序列中的每个元素应用一个函数,并返回处理后的结果组成的可迭代对象。
reduce()
:用于对序列中的元素逐个进行合并处理,并返回一个最终结果。
- 函数参数不同:
map()
接受一个函数和一个或多个序列(可迭代对象)作为参数,将函数应用于序列的每个元素,并返回结果组成的可迭代对象。
reduce()
接受一个二元函数和一个序列(可迭代对象)作为参数,该二元函数处理序列中的两个元素,并返回一个结果,然后将该结果与下一个元素继续进行处理,直到处理完所有元素并得到最终结果。
- 返回值不同:
map()
返回一个 map
对象,你可以将其转换成列表或其他类型的可迭代对象。
reduce()
返回一个最终的结果,而不是一个可迭代对象。
- 功能使用场景不同:
map()
适用于对序列中的每个元素进行相同的操作,例如对列表中的每个元素进行平方、转换为大写等。
reduce()
适用于对序列中的元素进行合并运算,例如求和、求积、找到最大值等。
综上所述,map()
用于对序列中的元素逐个进行相同的处理,而 reduce()
用于对序列中的元素进行累积合并操作。它们在不同的场景下有不同的应用。
例子:assic二进制转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| from functools import reduce from operator import add b = b'123' for i in b: print(i) print(bin(i)[2:].zfill(8)) print(list(map(int, bin(i)[2:].zfill(8)))) print(reduce(add, [list(map(int, bin(i)[2:].zfill(8))) for i in b])) ''' # 对应输出 49 # ascii 1 00110001 # 1的二进制 [0, 0, 1, 1, 0, 0, 0, 1] # 1的二进制的list 50 # ascii 2 00110010 # 2的二进制 [0, 0, 1, 1, 0, 0, 1, 0] # 2的二进制的list 51 00110011 [0, 0, 1, 1, 0, 0, 1, 1] # 二进制的list相加 [0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1] '''
|
字符串切片
当涉及到字符串切片,有很多有趣且实用的用法。以下是一些示例,展示了字符串切片的不同写法和妙用:
- 颠倒字符串
1 2 3 4
| s = "Hello, World!" reversed_string = s[::-1] print(reversed_string)
|
- 每隔一个字符获取一个子串
1 2 3 4
| s = "Hello, World!" every_other_char = s[::2] print(every_other_char)
|
- 获取从索引2到索引7之间的子串
1 2 3
| s = "Hello, World!" substring = s[2:8] print(substring)
|
- 获取从索引3开始,直到字符串结束的子串
1 2 3
| s = "Hello, World!" substring = s[3:] print(substring)
|
- 获取从字符串开始直到索引7之前的子串
1 2 3
| s = "Hello, World!" substring = s[:7] print(substring)
|
- 通过负数索引来获取子串
1 2 3
| s = "Hello, World!" substring = s[-6:-1] print(substring)
|
- 获取最后3个字符的子串
1 2 3
| es = "Hello, World!" last_three_chars = s[-3:] print(last_three_chars)
|
- 复制整个字符串
1 2 3
| s = "Hello, World!" copied_string = s[:] print(copied_string)
|
字符串常用前缀解释
在Python中,使用不同的前缀可以改变字符串的解释方式。
b
前缀(字节字符串): 使用b
前缀创建字节字符串,它表示以字节为单位的字符串,不会进行Unicode编码,适用于处理二进制数据。
1
| binary_data = b"Hello, world!"
|
r
前缀(原始字符串): 使用r
前缀创建原始字符串,该字符串中的转义字符(如\n
)不会被转义,适用于正则表达式、文件路径等。
1 2
| regex_pattern = r"\d{3}-\d{2}-\d{4}" file_path = r"C:\Users\username\file.txt"
|
u
前缀(Unicode字符串): 在Python 2.x 中,使用u
前缀创建Unicode字符串,表示字符串是以Unicode编码的。在Python 3中,字符串默认为Unicode,因此不再需要显式使用u
前缀。
1
| unicode_string = u"こんにちは"
|
f
前缀(格式化字符串): 使用f
前缀创建格式化字符串,可以在字符串中插入变量或表达式,并使用花括号 {}
来界定。
1 2 3
| name = "Alice" age = 30 formatted_string = f"My name is {name} and I am {age} years old."
|
Python正则表达式操作指南:re库的使用
基本函数介绍与示例
re.search(pattern, string)
搜索匹配模式的第一个位置
这个函数会在给定字符串中搜索匹配给定模式的第一个出现位置。如果找到匹配,它会返回一个匹配对象;如果没有找到,返回None
。
1 2 3 4 5 6 7
| pattern = r'\d{3}-\d{2}-\d{4}' text = "Date of birth: 01-15-1990" match = re.search(pattern, text) if match: print("Date found:", match.group()) else: print("Date not found")
|
在这个示例中,我们使用了\d{3}-\d{2}-\d{4}
的模式,它会匹配类似日期格式的字符串。search
函数找到匹配后,我们通过match.group()
获取匹配的字符串。
re.match(pattern, string)
从字符串开头匹配模式
这个函数会从字符串开头开始尝试匹配给定模式。如果在开头找到匹配,返回一个匹配对象;否则返回None
。
1 2 3 4 5 6 7
| pattern = r'Hello' text = "Hello, world!" match = re.match(pattern, text) if match: print("Matched:", match.group()) else: print("No match")
|
在这个示例中,我们使用了Hello
的模式,然后用match
函数尝试在开头匹配这个模式。在这种情况下,字符串开头的确匹配了模式。
re.findall(pattern, string)
查找所有匹配模式的子字符串
这个函数会查找并返回所有在字符串中匹配给定模式的子字符串。
1 2 3 4
| pattern = r'\d+' text = "There are 123 apples and 456 oranges." numbers = re.findall(pattern, text) print("Numbers:", numbers)
|
在这个示例中,我们使用了\d+
的模式,它会匹配连续的数字。findall
函数会返回所有匹配的数字子字符串。
re.finditer(pattern, string)
返回匹配模式的迭代器
这个函数返回一个迭代器,可以通过遍历获取所有在字符串中匹配给定模式的匹配对象。
1 2 3 4 5
| pattern = r'\b\w+\b' text = "Hello world, how are you?" matches = re.finditer(pattern, text) for match in matches: print("Word:", match.group())
|
在这个示例中,我们使用了\b\w+\b
的模式,它会匹配单词边界并提取单词。finditer
函数返回一个迭代器,通过遍历迭代器,我们可以获取每个匹配的单词。
re.sub(pattern, replacement, string)
- 替换匹配模式的字符串
这个函数会在字符串中查找匹配给定模式的子字符串,并将其替换为指定的字符串。
1 2 3 4
| pattern = r'apple' text = "I like apples, do you like apples?" new_text = re.sub(pattern, "orange", text) print("New text:", new_text)
|
在这个示例中,我们使用了apple
的模式,然后用sub
函数将所有的apple
替换为orange
。这样,我们得到了一个新的字符串。
re.split(pattern, string)
- 使用匹配模式分割字符串
这个函数会使用匹配给定模式的子字符串来分割字符串,返回分割后的部分列表。
1 2 3 4
| pattern = r'[,.]' text = "Hello, world. How are you?" parts = re.split(pattern, text) print("Parts:", parts)
|
在这个示例中,我们使用了[,.]
的模式,它会匹配逗号和句号。split
函数会使用这个模式来分割字符串,返回一个包含各个部分的列表。
提高效率的技巧
- 使用编译的正则表达式对象: 如果你在代码中多次使用同一模式,使用
re.compile()
函数创建一个编译过的正则表达式对象,以提高匹配效率。
1 2 3
| pattern = re.compile(r'\d{3}-\d{2}-\d{4}') text = "Dates: 01-01-2023 and 12-31-2023" dates = pattern.findall(text)
|
在这个示例中,我们首先使用re.compile()
编译了一个正则表达式对象,然后在不同的地方多次使用它来查找日期。
- 使用非贪婪模式: 非贪婪模式可以避免匹配时间过长。在量词后面加上
?
可以实现非贪婪匹配。
1 2 3 4
| pattern = r'<.*?>' pattern = r'<.*>' text = "<p>first</p><p>second</p>" matches = re.findall(pattern, text)
|
在这个示例中,我们演示了贪婪匹配和非贪婪匹配的区别。贪婪匹配会尽可能多地匹配字符,而非贪婪匹配只会匹配到第一个匹配。
- 使用字符集缩小匹配范围: 在字符集中使用只包含可能的字符,而不是使用点号(
.
),可以提高匹配速度。
1 2 3
| pattern = r'[aeiou]' text = "Hello, how are you?" vowels = re.findall(pattern, text)
|
在这个示例中,我们使用了字符集[aeiou]
来匹配元音字母。这比使用点号来匹配任意字符更有效率。
注意事项与常见错误
- 转义字符: 正则表达式中的一些字符具有特殊意义,需要使用反斜杠进行转义,如
\d
表示数字。如果你要匹配反斜杠本身,需要使用\\
。
- 原始字符串: 在正则表达式中,建议使用原始字符串(使用
r
前缀),以避免处理转义字符带来的麻烦。
- 量词和分组: 学习如何使用量词(
*
、+
、?
、{}
等)和分组来构建复杂的模式。
- 性能考虑: 正则表达式可能导致性能问题,特别是在处理大量数据时。要使用优化的模式和技巧来提高效率。
第三方库使用
send&recv:数据交互方式汇总
在 pwntools
库中,有几个常用的数据交互方法,包括 send
、sendline
、sendafter
、sendlineafter
、recvuntil
和 recv
,它们在与远程服务通信时都有不同的特性和用途。
send(date)
- 特性:发送指定的数据
data
给远程服务器,但不自动添加换行符。
- 区别:与
sendline
相比,不会自动添加换行符,需要手动处理数据格式。
- 使用情景:适用于发送不需要换行符结尾的数据,比如二进制数据或不需要自动回车的命令。
- 示例:
1 2 3 4
| r = remote('example.com', 1337)
r.send("Hello, world!")
|
sendline(data)
- 特性:发送指定的数据
data
给远程服务器,并自动添加换行符 (newline)。
- 区别:相比
send
,更方便发送带有换行符结尾的数据。
- 使用情景:适用于发送需要自动回车的命令,比如交互式命令行操作。
- 示例:
1 2 3 4
| r = remote('example.com', 1337)
r.sendline("login admin")
|
sendafter(sub, data)
- 特性:等待字符串
sub
在输出中出现,然后发送指定的数据 data
给远程服务器。
- 区别:用于在交互时根据之前输出的内容,自动判断何时发送数据。
- 使用情景:适用于根据程序输出的特定字符串来动态发送数据,典型用法是在登录过程中根据提示输入用户名和密码。
- 示例:
1 2 3 4 5 6 7 8
| r = remote('example.com', 1337)
r.sendafter("Username: ", "john_doe")
r.sendafter("Password: ", "secretpass")
|
sendlineafter(sub, data)
- 特性:等待字符串
sub
在输出中出现,然后发送指定的数据 data
给远程服务器,并自动添加换行符 (newline)。
- 区别:结合了
sendline
和 sendafter
的功能。
- 使用情景:适用于根据程序输出的特定字符串来动态发送需要自动回车的数据。
- 示例:
1 2 3 4 5 6 7 8
| r = remote('example.com', 1337)
r.sendlineafter("Enter your name: ", "Alice")
r.sendlineafter("Enter your age: ", "25")
|
recvuntil(delims)
- 特性:接收远程服务器的输出,直到遇到指定的分隔符
delims
。
- 区别:与
recv
相比,可以等待特定字符串之前的输出。
- 使用情景:适用于在得到某些输出之前,等待服务器输出的其他内容。
- 示例:
1 2 3 4 5 6 7 8
| r = remote('example.com', 1337)
output = r.recvuntil("Username: ")
print(output)
|
recv(n)
- 特性:接收指定字节数
n
的数据。
- 区别:与
recvuntil
相比,直接接收指定字节数的数据,不需要等待特定分隔符。
- 使用情景:适用于直接接收固定长度的数据。
- 示例:
1 2 3 4 5 6 7 8
| r = remote('example.com', 1337)
data = r.recv(1024)
print(data)
|
gdb查看内存命令
/s 查看相应地址的字符串
x/i 查看汇编指令
x/gx 查看相应地址的二进制信息
x/wx 按照字节形式显示二进制信息