User:Xyy23330121/Python/查漏补缺
在上面的学习中,有一些语句和程序结构因为暂时用不到,没有进行讲解。本页面将讲述这些内容。
内置函数 dir
会输出模块、类、函数等对象中,已有的属性、方法和函数列表。比如:
dir(float)
会输出:
['__abs__', '__add__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getformat__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'as_integer_ratio', 'conjugate', 'fromhex', 'hex', 'imag', 'is_integer', 'real']
这包含了 float 对象支持的一切方法和属性。
with 语句用于“上下文管理器”。
上下文管理器指的是拥有 __enter__
方法和 __exit__
方法的对象。其中:
__enter__
方法应不能额外传入参数__exit__
方法需要传入三个参数
我们看以下示例:
class Test:
def __enter__(self):
print("开始 with 语句")
return "value"
def __exit__(self, *args):
print("结束 with 语句")
return True
with Test() as a:
print(a)
该示例的输出为:
开始 with 语句
value
结束 with 语句
对于以下语句:
with ContextManager as var:
在执行 with 子句前,会调用 ContextManager.__enter__()
,并把其结果赋值给 var
,而在 with 子句执行后,会调用上下文管理器的 ContextManager.__exit__
方法。
特别的,可以省略 as var
。此时,with 语句不会进行最开始的赋值操作。
如果在 with 子句中没有引发错误,则在结束时,调用 ContextManager.__exit__(None, None, None)
。如果 with 子句中引发了错误,则这三个参数会包含错误信息。
此时,如果 ContextManager.__exit__
返回 True
,则不报错。如果返回 False
,则报错并退出。
我们看以下示例:
def prt(*items):
for item in items:
print(item)
print(type(item))
print("------------------")
class Test:
def __enter__(self): pass
def __exit__(self, a, b, c):
prt(a,b,c)
return False #如果出错,必定报错
with Test():
raise ValueError("示例错误信息")
该示例的输出为:
<class 'ValueError'>
<class 'type'>
------------------
示例错误信息
<class 'ValueError'>
------------------
<traceback object at 0x00000137E51F5000>
<class 'traceback'>
------------------
Traceback (most recent call last):
...
raise ValueError("示例错误信息")
ValueError: 示例错误信息
可以看出,传入的参数按顺序分别为错误对象的类型、错误对象、Traceback。
需要注意的是,如果 with 子句中没有产生错误,则无论 __exit__
返回什么值,都不会报错。
match 语句是 Python 3.10 版本加入的语句。它和 if 语句的作用类似,但功能更强大,语法也更复杂。
由于 match 语句集“赋值”和“比较”两个方式为一体,且两个方式的区分在 Python 文档中没有严格地定义,所以这里只讲解最简单的“比较”方式,而完全跳过“赋值”的部分。
boolean = True
match boolean:
case True:
print("True")
case False:
print("False")
case True:
print("不会匹配到这里,因为已经有匹配值了")
在“匹配”时,case 后面不可以跟着任何变量名称,而必须是 0
、"str"
之类的字面值。或者,也可以是只由类型构造器构成的表达式。
类型构造器就是int(x)
这类,调用时和函数的方法一致——但直接用于构造类的实例的方式。
在这种情况下,match 语句和 if 语句作用是完全相同的。它会尝试将 match 关键字后紧跟着的、表达式的结果和 case 语句后紧跟着的内容作比较。如果和某个 case 匹配,则会执行匹配的 case 子句。执行完成后,不会再进行匹配。
yield 语句用于创建“生成器函数”。
我们之前接触过生成器,我们在列表和元组的括号内使用过生成器,比如:
print(i**2 for i in range(3)) #输出:<generator object <genexpr> at *>
生成器是一种迭代器。对于这种方法所创建的生成器,我们可以用函数的方式获取:
def identity(x):
return x
a = identity(i**2 for i in range(3))
for i in a:
print(i, end=" ") #输出:0 1 4
当一个函数中包含 yield 语句时,这个函数就会变成“生成器函数”。我们看以下示例:
def sliced(start=0, end=3):
now = start
while now < end:
yield now
now += 1
print(sliced) #输出:<function sliced at *>
print(sliced()) #输出:<generator object sliced at *>
for i in sliced():
print(i,end=" ") #输出:0 1 2
生成器函数所返回的对象是一个生成器。该函数所返回的生成器,其中的元素就是每一次调用 yield 表达式时、yield 表达式的值。
使用 yield from 语句,可以将迭代器中的元素加入到返回的生成器中。
def gf():
yield from "123"
yield from [1,2,3]
yield "end"
for i in gf():
print(i,end=" ") #输出:1 2 3 1 2 3 end
除了用 for 语句调用之外,还可以用 next
函数来读取生成器中的值。比如:
def g():
yield 1
yield 2
generator = g()
print(next(generator)) #输出:1
print(next(generator)) #输出:2
print(next(generator)) #报错:StopIteration
next 函数对于一般的迭代器也是适用的,以下内容和上面内容的输出完全一致:
iterator = iter([1,2])
print(next(iterator))
print(next(iterator))
print(next(iterator))
钩子(Hook)指的是监测某个事件发生的程序。当事件发生时,钩子会按照设置执行对应的程序。以下是带有钩子的一个对象的示例:
class StrHook():
def __init__(self, obj, hook=None):
self.obj = obj
self.hook= hook
def __str__(self):
#当执行 __str__ 方法时,如果设置了钩子,则触发钩子的内容。
if self.hook != None:
self.hook(self.obj)
return str(self.obj)
def func(obj):
print(obj,"执行了 __str__ 方法")
#创建对象
a = StrHook(123, hook=func)
#尝试触发对象的钩子
b = str(a)
输出为:
123 执行了 __str__ 方法