使用者: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__ 方法