我有一個方法接收共享一個公共超類但具有許多不同子型別的物件。它檢查每個物件的型別,并根據型別將其傳遞給不同的函式。接收器函式被注釋以接收特定的子型別。
物件型別是提前知道的,并且是有限集合的一部分。物件只會是深度 1 的子類,而不是子子類。
此代碼對性能非常關鍵。為了避免isinstance分派時多次呼叫的開銷,我將型別存盤在一個變數中。
但是,我無法讓 PyC??harm 根據存盤的型別變數檢測每個物件的“特化”。它表示型別錯誤,因為我將其型別只知道作為超類的物件傳遞給接收特定子類的函式。
例如,我的代碼如下所示:
class Superclass: ...
class Subtype1(Superclass): ...
class Subtype2(Superclass): ...
# ...many more subtypes
def receiver1(arg: Subtype1): ...
def receiver2(arg: Subtype2): ...
# ...many more receivers
def dispatch():
item = get_item()
item_type = type(item)
if item_type is Subtype1:
receiver(item)
elif item_type is Subtype2:
receiver2(item)
# ... many more cases
receiver1使用該代碼,PyCharm 會檢測對和的呼叫的型別不匹配receiver2。
通常,我會在這里放棄,因為 Python 是一種動態型別的語言,堅持讓 IDE 在結構上理解以動態型別調度的代碼似乎是不合理的。
但是,PyCharm 可以做到這一點。它似乎只適用于isinstance支票。如果我dispatch用下面的代碼替換,PyCharm 型別會正確檢查它:
def dispatch():
item = get_item()
if isinstance(item, Subtype1):
receiver1(item)
elif isinstance(item, Subtype2):
receiver2(item)
# ... many more cases
問題是,這太慢了。isinstance本身比比較慢得多is,我必須多次呼叫它來檢查每個案例;有很多情況。
有沒有辦法讓 PyC??harm 在不使用的情況下檢測簡單的專業化型別isinstance?如果是這樣,怎么做?
我試過的
- 通常,這將非常適合面向物件。如果
receiver函式是每個子型別的方法,我可以簡單地呼叫item.recieve()或每次。但是,子型別是在我無法控制的代碼中宣告的(并且是在 C 中實作的記錄類,因此它們不能被子類化——我知道這很奇怪,但我確實否認它是性能關鍵代碼:))。 - 各種使用
dict型別鍵控和接收器方法作為值的調度表方法同樣會破壞 PyCharm 的型別檢查。
uj5u.com熱心網友回復:
你可以給 PyCharm 額外的型別提示
def dispatch():
item = get_item()
item_type = type(item)
if item_type is Subtype1:
item: Subtype1
receiver1(item)
elif item_type is Subtype2:
item: Subtype2
receiver2(item)
這不應該影響代碼的性能。
另一種方法是將接收器方法注入 Subtype1/2 類:
def receiver1(arg: Subtype1):
print("receiver1 called")
def receiver2(arg: Subtype2):
print("receiver2 called")
class MyMeta(type):
pass
d = dict(Subtype1.__dict__)
d.update({"receiver": receiver1})
Subtype1 = MyMeta(Subtype1.__name__,
Subtype1.__bases__,
d)
d = dict(Subtype2.__dict__)
d.update({"receiver": receiver2})
Subtype2 = MyMeta(Subtype2.__name__,
Subtype2.__bases__,
d)
def dispatch():
item = get_item()
item.receiver()
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/459983.html
上一篇:在派生類中深度復制指標向量
