2017-06-19 4 views
2

@classmethodclsのインスタンスを返すアノテーションをどうすればよいですか?ここでは悪い例です:インスタンスを返すクラスメソッドのMyPyアノテーション

class Foo(object): 
    def __init__(self, bar: str): 
     self.bar = bar 

    @classmethod 
    def with_stuff_appended(cls, bar: str) -> ???: 
     return cls(bar + "stuff") 

これはFooを返しますが、より正確には十分ではありませんので、-> "Foo"による注記を、上と呼ばれFooこののいずれかのサブクラスを返します。

+0

' - > 'Foo''は正しいです、それはあなたが返す値について強制することができます(またはそうするべきです)。 – jonrsharpe

答えて

2

トリックを明示的にそうように、represent a class rather then the instance itselfに、genericsため、TypeVarとの組み合わせで、clsパラメータに注釈を追加し、Typeすることです:

from typing import TypeVar, Type 

# Create a generic variable that can be 'Parent', or any subclass. 
T = TypeVar('T', bound='Parent') 

class Parent: 
    def __init__(self, bar: str) -> None: 
     self.bar = bar 

    @classmethod 
    def with_stuff_appended(cls: Type[T], bar: str) -> T: 
     # We annotate 'cls' with a typevar so that we can 
     # type our return type more precisely 
     return cls(bar + "stuff") 

class Child(Parent): 
    # If you're going to redefine __init__, make sure it 
    # has a signature that's compatible with the Parent's __init__, 
    # since mypy currently doesn't check for that. 

    def child_only(self) -> int: 
     return 3 

# Mypy correctly infers that p is of type 'Parent', 
# and c is of type 'Child'. 
p = Parent.with_stuff_appended("10") 
c = Child.with_stuff_appended("20") 

# We can verify this ourself by using the special 'reveal_type' 
# function. Be sure to delete these lines before running your 
# code -- this function is something only mypy understands 
# (it's meant to help with debugging your types). 
reveal_type(p) # Revealed type is 'test.Parent*' 
reveal_type(c) # Revealed type is 'test.Child*' 

# So, these all typecheck 
print(p.bar) 
print(c.bar) 
print(c.child_only()) 

通常は、cls(とselfを残すことができます)は注釈を付けませんが、特定のサブクラスを参照する必要がある場合は、explicit annotationを追加できます。この機能はまだ実験中であり、場合によってはバグの可能性があることに注意してください。 pypiで利用できるものではなく、Githubからクローン化されたmypyの最新バージョンを使用する必要があるかもしれません。クラスメイトのこの機能をサポートしているかどうかはわかりません。

+1

通常のmypy作品:) – taway

+0

@taway - ハァッ、クール!私はそれがしなかったと誓っていたかもしれませんが、私が間違っていると聞いてうれしいです! – Michael0x2a

関連する問題