Python | 八、类型注解、解包操作符*、del关键字、@符号、正则表达式

类型注解

  • 类型注解(Type Annotations)在Python 3.5及更高版本中被引入。类型注解允许你为函数的参数和返回值指定预期的数据类型。这些注解不会对Python代码的运行时行为产生直接影响,也就是说,它们不会导致代码在运行时进行类型检查或强制类型转换。它们主要是用于代码文档目的,使得代码更容易理解和维护,同时也便于类型检查工具和IDEs进行静态分析,以发现潜在的类型错误。
  • Python的类型注解语法遵循几个基本规则,使得代码能够包含关于变量、函数参数和返回值类型的元数据。这里是一些基本的规则和示例:
    • 变量类型注解(包括函数形参),对于变量,类型注解紧跟在变量名后面,使用冒号分隔,并指定类型 a: int = 5
    • 函数返回值类型注解,对于函数返回值,类型注解位于函数声明的末尾,前面使用->符号,然后是返回值的类型。如果函数没有返回值(或者说返回None),可以使用-> None:def add(x: int, y: int) -> int:
    • 容器和复杂类型,对于列表、字典、元组等容器或复杂类型,可以使用typing模块中定义的泛型类(如List、Dict、Tuple等)来指定容器中元素的类型:
    • 可选类型和并集类型,对于可能为None或其他类型的变量,可以使用Optional类型。对于可以是多个类型之一的变量,可以使用Union类型:
    • 类型别名,对于复杂的类型注解,可以使用类型别名简化代码:
# 容器和复杂类型举例
from typing import List, Dict, Tuple

names: List[str] = ["Alice", "Bob", "Charlie"]
scores: Dict[str, int] = {"math": 90, "science": 95}
coordinate: Tuple[int, int, int] = (10, 20, 30)
# 可选类型和并集类型举例
from typing import Optional, Union

maybe_number: Optional[int] = None  # 可以是int类型,也可以是None
number_or_string: Union[int, str] = 5  # 可以是int类型,也可以是str类型
# 类型别名举例
from typing import Dict, List

Scores = Dict[str, int]
ClassScores = Dict[str, Scores]

class_scores: ClassScores = {"class1": {"Alice": 95, "Bob": 85}}

解包操作符*

  • 解包操作符在Python中是一种非常有用的语法特性,允许我们在调用函数时,将可迭代对象(如列表、元组、集合等)“解包”成位置参数,或将字典解包成关键字参数。Python中有两种解包操作符:* 用于列表、元组等,而 ** 用于字典。
  • * 操作符用于非键值对的可迭代对象,如列表、元组。当在函数调用中使用*时,它会将可迭代对象中的每个元素作为单独的参数传递给函数。这在你有一个列表或元组,并希望将其元素作为独立参数传递给函数时非常有用
# 示例
def sum(a, b, c):
    return a + b + c

values = [1, 2, 3]

# 使用解包操作符调用函数
result = sum(*values)  # 等同于调用 sum(1, 2, 3)
print(result)
  • ** 操作符用于字典,允许你将字典的键值对作为关键字参数传递给函数。这意味着字典的键必须是字符串,因为它们将被用作参数的名称。
# 示例
def greet(name, greeting):
    return f"{greeting}, {name}!"

person = {'name': 'Alice', 'greeting': 'Hello'}

# 使用解包操作符调用函数
message = greet(**person)  # 等同于调用 greet(name='Alice', greeting='Hello')
print(message)
  • 在函数定义中使用解包操作符
    解包操作符不仅可以在调用函数时使用,还可以在定义函数时使用,以接受任意数量的位置参数或关键字参数。
    • 使用*args在函数定义中收集任意数量的位置参数到一个元组中。
    • 使用**kwargs在函数定义中收集任意数量的关键字参数到一个字典中。
# 示例
def example_func(*args, **kwargs):
    print(args)   # 显示位置参数
    print(kwargs)  # 显示关键字参数

example_func(1, 2, 3, key1='value1', key2='value2')

del关键字

  • del 关键字在 Python 中用于删除对象。使用 del 可以删除变量、列表的元素、字典中的键值对等。del 实际上是调用了对象的 del() 方法,如果对象是一个复杂对象,比如类的实例,del 将调用该对象的析构函数,以便进行清理操作
  • del 不会删除对象本身,而是删除对对象的引用。如果对象的引用计数降到 0,Python 的垃圾回收器将回收这个对象。此外,del 关键字的使用需要谨慎,因为一旦使用 del 删除了某个对象或变量的引用,就无法再访问该对象或变量了,除非重新创建或定义
  • 如果定义了一个对象,也可以使用 del 删除其属性,如del obj.attribute

@符号

  • 在 Python 中,@ 符号有几种不同的用途,其中最常见的是作为装饰器(Decorator)和进行矩阵乘法的运算符
  • 装饰器(Decorator)
    • 装饰器是一种高阶函数,它允许你修改或增强其他函数或方法的功能。在 Python 中,装饰器通常使用 @ 符号来应用。这样可以在不修改原有函数代码的情况下,增加函数的额外功能,如日志记录、性能测试、事务处理等
    • 例如,一个简单的装饰器,用于在函数调用前后打印信息(在这个例子中,@my_decorator 将 say_hello 函数封装在 wrapper 函数中,增加了在调用前后打印信息的功能)
def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
  • 矩阵乘法
    • 从 Python 3.5 开始,@ 符号被引入作为矩阵乘法的运算符。这在使用 NumPy 或其他支持矩阵操作的库时非常有用,可以直接使用 @ 来替代传统的矩阵乘法函数,使代码更加简洁明了
    • 举例
import numpy as np

a = np.array([[1, 2], [3, 4]])
b = np.array([[2, 0], [1, 2]])

result = a @ b
print(result)

正则表达式

  • Python 的正则表达式是一种用于字符串搜索和操作的强大工具,通过特定的模式来匹配字符串中的字符组合。在 Python 中,正则表达式主要通过 re(Regular Expression) 模块实现,该模块提供了一系列函数来处理正则表达式。
  • 常用的正则表达式函数
    • re.match(pattern, string, flags=0):尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
    • re.search(pattern, string, flags=0):扫描整个字符串并返回第一个成功的匹配。
    • re.findall(pattern, string, flags=0):找到字符串中所有匹配的子串,并返回一个列表。
    • re.finditer(pattern, string, flags=0):找到字符串中所有匹配的子串,并返回一个迭代器。
    • re.sub(pattern, repl, string, count=0, flags=0):替换字符串中的匹配项。
    • re.compile(pattern, flags=0):编译一个正则表达式模式,返回一个对象,用于匹配。
  • 正则表达式的模式
    • 正则表达式通过特定的符号指定模式,以下是一些常用的正则表达式符号:
      • .:匹配除了新行以外的任何单个字符。(如果要匹配点的话就用转义字符’\.')
      • ^:匹配字符串的开头。
      • $:匹配字符串的末尾。
      • *:匹配0次或多次前面的正则表达式。
      • +:匹配1次或多次前面的正则表达式。
      • ?:匹配0次或1次前面的正则表达式。
      • {m}:匹配m次前面的正则表达式。
      • {m,n}:匹配从m到n次前面的正则表达式。
      • [abc]:匹配方括号内的任意一个字符(在这里是a、b或c)。
      • [^abc]:匹配不在方括号内的任意字符。
      • \b 代表单词边界。它用来指明一个位置,这个位置前后字符之间应满足一个字符是单词字符(字母、数字、下划线)而另一个不是单词字符的条件
      • \d:匹配任何数字,等价于[0-9]。
      • \D:匹配任何非数字字符,等价于[^0-9]。
      • \s:匹配任何空白字符,等价于[\t\n\r\f\v]。
      • \S:匹配任何非空白字符。
      • \w:匹配任何字母数字字符,等价于[a-zA-Z0-9_]。
      • \W:匹配任何非字母数字字符。
  • 举例
    • 在一段文本中找到所有的电子邮件地址,可以使用如下正则表达式
import re
text = "联系我通过email: example@test.com, 或者 alternate_email@test.com"
emails = re.findall(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', text)
print(emails)
# \b - 单词边界。这确保了我们的模式匹配从单词的开头开始,并在单词的末尾结束,防止匹配到域名或邮箱用户名的一部分。
# [A-Za-z0-9._%+-]+ - 这是一个字符集,匹配所有大写字母、小写字母、数字、下划线、点、百分号、加号和减号。加号 (+) 表示前面的字符集中的字符出现一次或多次。这部分用于匹配电子邮件地址的“用户名”部分。
# @ - 字符 "@" 在电子邮件地址中用作分隔符,区分用户名和域名。
# [A-Za-z0-9.-]+ - 这部分匹配域名中的字母、数字、点和破折号。这里的加号 (+) 同样表示前面的字符集中的字符出现一次或多次。
# \. - 字符 "." 用于分隔域名和顶级域名(TLD)。在正则表达式中,点号通常表示任意字符,所以它前面用反斜杠进行了转义,以表示字面意义上的点号。
# [A-Z|a-z]{2,} - 这部分匹配顶级域名,可以是两个或更多的字母。中括号内的 A-Z|a-z 表示匹配任何大小写字母,花括号 {2,} 指定匹配长度至少为2。
# \b - 又一个单词边界,确保匹配到的邮箱地址在字符串中是独立的单词。
  • 找电话号码(1开头,11位)
import re

# 示例文本
text = "我的号码是 13912345678,请联系我。另一个号码是 18898765432。"

# 正则表达式模式
# 假定手机号码被空格、标点或行结束符界定
pattern = r'\b1[3-9]\d{9}\b'
# 在 Python 中,字符串前的 r 表示一个原始字符串(raw string)。
# 使用原始字符串是为了告诉 Python 解释器不要处理(或“转义”)字符串中的转义字符
# \b 表示单词边界,确保号码不是被其他数字包围(即确保号码是独立的部分)。
# 1 是中国手机号码的起始数字。
# [3-9] 表示第二位数字可以是 3 到 9 之间的任意一位,覆盖当前的手机号码规则。
# \d{9} 表示接下来是任意 9 个数字。
# \b 表示单词边界的结束。

# 查找所有匹配的手机号码
matches = re.findall(pattern, text)

# 输出匹配的手机号码
print(matches)
  • 16
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值