pythonジェネリック/テンプレートタイプのシナリオをどのように処理しますか?外部ファイル "BinaryTree.py"を作成し、バイナリデータをすべてのデータタイプに対応させたいとします。
したがって、カスタムオブジェクトの型を渡し、そのオブジェクトのバイナリツリーを作成できます。これはPythonでどのように行われますか?
Pythonは ダックタイピング を使用するため、複数のタイプを処理するための特別な構文は必要ありません。
C++のバックグラウンドを使用している場合、テンプレート関数/クラスで使用される操作がT
(構文レベル)の一部の型で定義されている限り、その型を使用できることを覚えているでしょう。テンプレートのT
。
したがって、基本的には同じように機能します。
ただし、明示的な型チェック(通常は推奨されません)を記述しない限り、選択した型の要素のみがバイナリツリーに含まれることを強制することはできません。
実際には、Python 3.5+。でジェネリックを使用できます。 PEP-484 および typing library documentation を参照してください。
私の慣習によれば、特にJava Genericsに精通しているが、まだ使用可能な人にとっては、それほどシームレスで明確ではありません。
Pythonでジェネリック型を作成することについていくつかの良い考えを思いついた後、同じアイデアを持っている他の人を探し始めましたが、何も見つかりませんでした。だから、ここにある。これを試してみましたが、うまくいきます。これにより、Pythonで型をパラメーター化できます。
_class List( type ):
def __new__( type_ref, member_type ):
class List( list ):
def append( self, member ):
if not isinstance( member, member_type ):
raise TypeError( 'Attempted to append a "{0}" to a "{1}" which only takes a "{2}"'.format(
type( member ).__name__,
type( self ).__name__,
member_type.__) )
list.append( self, member )
return List
_
これで、このジェネリック型から型を派生できます。
_class TestMember:
pass
class TestList( List( TestMember ) ):
def __init__( self ):
super().__init__()
test_list = TestList()
test_list.append( TestMember() )
test_list.append( 'test' ) # This line will raise an exception
_
このソリューションは単純化されており、制限があります。ジェネリック型を作成するたびに、新しい型が作成されます。したがって、List( str )
を親として継承する複数のクラスは、2つの別個のクラスから継承します。これを克服するには、新しいクラスを作成するのではなく、内部クラスのさまざまな形式を格納し、以前に作成した内部クラスを返すための辞書を作成する必要があります。これにより、同じパラメーターを持つ重複タイプが作成されなくなります。興味があれば、デコレータやメタクラスを使用してよりエレガントなソリューションを作成できます。
pythonは動的に型指定されるため、これは非常に簡単です。実際、BinaryTreeクラスがデータ型と連動しないようにするには、余分な作業を行う必要があります。
たとえば、key()
などのメソッドからオブジェクト内のオブジェクトをツリーに配置するために使用されるキー値が必要な場合は、オブジェクトでkey()
を呼び出すだけです。例えば:
_class BinaryTree(object):
def insert(self, object_to_insert):
key = object_to_insert.key()
_
Object_to_insertの種類を定義する必要は決してないことに注意してください。 key()
メソッドがあれば機能します。
例外は、文字列や整数などの基本的なデータ型で動作させたい場合です。それらをクラスにラップして、ジェネリックBinaryTreeで動作させる必要があります。それが重すぎるように聞こえ、実際に文字列を保存するだけの余分な効率が必要な場合は、申し訳ありませんが、それはPythonが得意ではありません。
Pythonは動的に型指定されるため、オブジェクトの型は多くの場合重要ではありません。何でも受け入れることをお勧めします。
私が意味することを示すために、このツリークラスは2つのブランチに対して何でも受け入れます。
class BinaryTree:
def __init__(self, left, right):
self.left, self.right = left, right
そして、次のように使用できます。
branch1 = BinaryTree(1,2)
myitem = MyClass()
branch2 = BinaryTree(myitem, None)
tree = BinaryTree(branch1, branch2)
組み込みのコンテナがどのようにそれを行うかを見てください。 dict
およびlist
などには、任意のタイプの異種要素が含まれます。たとえば、ツリーのinsert(val)
関数を定義すると、ある時点でnode.value = val
とPythonが残りを処理します。
幸いなことにpython。の一般的なプログラミングのためのいくつかの努力がありました。ライブラリがあります: generic
以下にそのドキュメントを示します。 http://generic.readthedocs.org/en/latest/
それは何年にもわたって進歩していませんが、あなたはあなた自身のライブラリをどのように使い、作るかについて大まかな考えを持つことができます。
乾杯
Python 2を使用する場合、またはJavaコードを書き直したい場合。これは実際の解決策ではありません。 https://github.com/FlorianSteenbuck/python-generics 私はまだコンパイラを入手していないので、あなたは現在そのように使用しています:
class A(GenericObject):
def __init__(self, *args, **kwargs):
GenericObject.__init__(self, [
['b',extends,int],
['a',extends,str],
[0,extends,bool],
['T',extends,float]
], *args, **kwargs)
def _init(self, c, a, b):
print "success c="+str(c)+" a="+str(a)+" b="+str(b)
TODO
<? extends List<Number>>
)super
サポートを追加?
サポート