12

私は、クラスの継承、抽象基本クラス、さらにはPythonインターフェースについて説明しているドキュメントを読んでいます。しかし、私が望んでいるものとまったく同じになるものは何もありません。つまり、仮想クラスを構築する簡単な方法です。仮想クラスが呼び出されたら、与えられたパラメーターに基づいてより具体的なクラスをインスタンス化し、呼び出し元の関数に返します。今のところ、仮想クラスへの呼び出しを基になるクラスに再ルーティングする簡単な方法があります。

アイデアは次のとおりです。

class Shape:
    def __init__(self, description):
        if   description == "It's flat":  self.underlying_class = Line(description)
        elif description == "It's spiky": self.underlying_class = Triangle(description)
        elif description == "It's big":   self.underlying_class = Rectangle(description)
    def number_of_edges(self, parameters):
        return self.underlying_class(parameters)

class Line:
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 1

class Triangle:
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 3

class Rectangle:
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 4

shape_dont_know_what_it_is = Shape("It's big")
shape_dont_know_what_it_is.number_of_edges(parameters)

number_of_edges()関数への呼び出しのみが渡されるため、私の再ルーティングは最適とはほど遠いものです。このようなものをShapeに追加しても、そのトリックを実行するために継ぎ目はありません。

def __getattr__(self, *args):
    return underlying_class.__getattr__(*args)

私が間違っていることは何ですか?アイデア全体がうまく実装されていませんか?どんな助けでも大歓迎です。

4

4 に答える 4

18

TooAngelに同意しますが、 __new__メソッドを使用します。

class Shape(object):
    def __new__(cls, *args, **kwargs):
        if cls is Shape:                            # <-- required because Line's
            description, args = args[0], args[1:]   #     __new__ method is the
            if description == "It's flat":          #     same as Shape's
                new_cls = Line
            else:
                raise ValueError("Invalid description: {}.".format(description))
        else:
            new_cls = cls
        return super(Shape, cls).__new__(new_cls, *args, **kwargs)

    def number_of_edges(self):
        return "A shape can have many edges…"

class Line(Shape):
    def number_of_edges(self):
        return 1

class SomeShape(Shape):
    pass

>>> l1 = Shape("It's flat")
>>> l1.number_of_edges()
1
>>> l2 = Line()
>>> l2.number_of_edges()
1
>>> u = SomeShape()
>>> u.number_of_edges()
'A shape can have many edges…'
>>> s = Shape("Hexagon")
ValueError: Invalid description: Hexagon.
于 2010-06-19T18:03:21.620 に答える
15

私はそれを工場で行うことを好みます:

def factory(description):
    if   description == "It's flat":  return Line(description)
    elif description == "It's spiky": return Triangle(description)
    elif description == "It's big":   return Rectangle(description)

また:

def factory(description):
    classDict = {"It's flat":Line("It's flat"), "It's spiky":Triangle("It's spiky"), "It's big":Rectangle("It's big")}
    return classDict[description]

Shapeからクラスを継承します

class Line(Shape):
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 1
于 2010-06-19T17:39:46.813 に答える
1

Pythonには、すぐに使用できる仮想クラスはありません。それらを自分で実装する必要があります(Pythonのリフレクション機能は、これを実行できるほど強力である必要があります)。

ただし、仮想クラスが必要な場合は、Beta、gBeta、Newspeakなどの仮想クラスを備えたプログラミング言語を使用してみませんか?(ところで:他に何かありますか?)

ただし、この特定のケースでは、少なくともあなたが与えた例では、仮想クラスがソリューションをどのように単純化するかは実際にはわかりません。おそらく、仮想クラスが必要だと思う理由を詳しく説明できますか?

誤解しないでください。私は仮想クラスが好きですが、仮想クラスを実装したのは3つの言語だけであり、まだ生きているのは3つのうちの1つだけであり、実際に誰かが使用しているのは3つのうちの0つだけです。

于 2010-06-19T17:55:56.900 に答える
0

でクラスを変更できobject.__class__ますが、任意のクラスのインスタンスを返す関数を作成する方がはるかに優れています。

別の注意点として、objectこのようにPython 3を使用しない限り、すべてのクラスはから継承する必要があります。そうしないと、古いスタイルのクラスになってしまいます。

class A(object):
    pass
于 2010-06-19T17:46:29.853 に答える