TL; DR : Python 4.0 kullanıyorsanız işe yarıyor. Bugün (2019) 3.7 ve sonraki sürümlerinde bu özelliği gelecekteki bir ifadeyi ( from __future__ import annotations
) kullanarak açmalısınız - Python 3.6 veya daha düşük sürümler için bir dize kullanın.
Sanırım şu istisnayı yakaladınız:
NameError: name 'Position' is not defined
Bunun nedeni Position
, Python 4'ü kullanmadığınız sürece bir ek açıklamada kullanabilmeniz için tanımlanması gerektiğidir.
Python 3.7+: from __future__ import annotations
Python 3.7, PEP 563'ü sunar: ek açıklamaların ertelenmesi . Future ifadesini kullanan bir modül from __future__ import annotations
ek açıklamaları otomatik olarak dize olarak saklar:
from __future__ import annotations
class Position:
def __add__(self, other: Position) -> Position:
...
Bunun Python 4.0'da varsayılan olması planlanmıştır. Python hala dinamik olarak yazılan bir dil olduğundan, çalışma zamanında tür denetimi yapılmadığından, ek açıklamaların performans etkisi olmaması gerekir, değil mi? Yanlış! Piton 3.7 eskiden yazarak modülü önce çekirdekte en yavaş piton modüllerinden biri böylece eğer import typing
göreceksiniz kez performansında artış 7'ye kadar sen 3.7 yükselttiğinizde.
Python <3.7: bir dize kullanın
PEP 484'e göre , sınıfın kendisi yerine bir dize kullanmalısınız:
class Position:
...
def __add__(self, other: 'Position') -> 'Position':
...
Django çerçevesini kullanırsanız, Django modelleri ayrıca ileri başvurular için dizeler kullandığından (yabancı modelin self
henüz bildirilmediği veya henüz bildirilmediği yabancı anahtar tanımları) tanıdık gelebilir . Bu Pycharm ve diğer araçlarla çalışmalıdır.
Kaynaklar
PEP 484 ve PEP 563'ün ilgili bölümleri , seyahatinizi yedeklemek için:
İleri referanslar
Bir tür ipucu henüz tanımlanmamış adlar içerdiğinde, bu tanım daha sonra çözümlenecek bir dize hazır bilgisi olarak ifade edilebilir.
Bunun yaygın olarak meydana geldiği bir durum, tanımlanmış sınıfın bazı yöntemlerin imzasında gerçekleştiği bir konteyner sınıfının tanımıdır. Örneğin, aşağıdaki kod (basit bir ikili ağaç uygulamasının başlangıcı) çalışmaz:
class Tree:
def __init__(self, left: Tree, right: Tree):
self.left = left
self.right = right
Bunu ele almak için şunu yazıyoruz:
class Tree:
def __init__(self, left: 'Tree', right: 'Tree'):
self.left = left
self.right = right
Dize değişmez değeri geçerli bir Python ifadesi içermelidir (yani, derleme (lit, '', 'eval') geçerli bir kod nesnesi olmalıdır) ve modül tamamen yüklendikten sonra hatasız olarak değerlendirilmelidir. Değerlendirildiği yerel ve global ad alanı, aynı işleve ait varsayılan bağımsız değişkenlerin değerlendirileceği ad alanları ile aynı olmalıdır.
ve PEP 563:
Python 4.0'da, işlev ve değişken ek açıklamaları artık tanımlama zamanında değerlendirilmez. Bunun yerine, ilgili __annotations__
sözlükte bir dize formu korunur . Statik tip denetleyicilerin davranışlarında hiçbir fark görülmezken, çalışma zamanında ek açıklamaları kullanan araçların ertelenmiş değerlendirme yapması gerekir.
...
Yukarıda açıklanan işlevsellik, aşağıdaki özel içe aktarma kullanılarak Python 3.7'den başlayarak etkinleştirilebilir:
from __future__ import annotations
Bunun yerine yapmak isteyebileceğiniz şeyler
A. Bir kukla tanımlayın Position
Sınıf tanımından önce kukla bir tanım yerleştirin:
class Position(object):
pass
class Position(object):
...
Bu kurtulur NameError
ve hatta Tamam görünebilir:
>>> Position.__add__.__annotations__
{'other': __main__.Position, 'return': __main__.Position}
Ama öyle mi?
>>> for k, v in Position.__add__.__annotations__.items():
... print(k, 'is Position:', v is Position)
return is Position: False
other is Position: False
Ek açıklama eklemek için maymun yaması:
Ek açıklamalar eklemek için bazı Python meta programlama sihirlerini denemek ve sınıf tanımını maymun yaması için bir dekoratör yazmak isteyebilirsiniz:
class Position:
...
def __add__(self, other):
return self.__class__(self.x + other.x, self.y + other.y)
Dekoratör, bunun eşdeğerinden sorumlu olmalıdır:
Position.__add__.__annotations__['return'] = Position
Position.__add__.__annotations__['other'] = Position
En azından doğru görünüyor:
>>> for k, v in Position.__add__.__annotations__.items():
... print(k, 'is Position:', v is Position)
return is Position: True
other is Position: True
Muhtemelen çok fazla sorun var.
Sonuç
3.6 veya daha düşük bir değer kullanıyorsanız, 3.7 adını kullanarak sınıf adını içeren bir dize değişmez değeri kullanın from __future__ import annotations
ve bu sadece işe yarayacaktır.