11

Scala では、抽象クラスを定義し、それをオブジェクトで実装できます。

abstrac class Base {
    def doSomething(x: Int): Int
}

object MySingletonAndLiteralObject extends Base {
    override def doSomething(x: Int) = x*x
}

Python での私の具体的な例:

class Book(Resource):

    path = "/book/{id}"

    def get(request):
        return aBook

2 つのクラスが同じ を持つことはできないため、継承はここでは意味がありませんpath。また、クラスがオブジェクトの青写真として機能しないように、必要なインスタンスは 1 つだけです。つまり、Resource(Book私の例では) にはクラスは必要ありませんが、共通の機能を提供するには基本クラスが必要です。

私がしたい:

object Book(Resource):

    path = "/book/{id}"

    def get(request):
        return aBook

それを行うためのPython 3の方法は何でしょうか?

4

3 に答える 3

7

デコレーターを使用して、作成時に継承されたクラスをオブジェクトに変換します

このようなオブジェクトの概念は、Python でのコーディングの典型的な方法ではないと思いますが、必要な場合は、class_to_objectすぐに初期化するための以下のデコレータがうまく機能します。オブジェクトの初期化のパラメータはすべてデコレータを介して渡す必要があることに注意してください。

def class_to_object(*args):
    def c2obj(cls):
        return cls(*args)
    return c2obj

このデコレータを使用して取得します

>>> @class_to_object(42)
... class K(object):
...     def __init__(self, value):
...         self.value = value
... 
>>> K
<__main__.K object at 0x38f510>
>>> K.value
42

最終結果としてK、scala オブジェクトに似たオブジェクトが作成され、他のオブジェクトを初期化するためのクラスが名前空間にありません。

注: 分かりやすく説明すると、オブジェクト K のクラスは次のように取得できるためK.__class__、誰かが本当に必要に応じて他のオブジェクトを初期化することができます。Python では、本当に必要な場合は、ほとんどの場合、回避策があります。

于 2010-08-19T12:37:44.047 に答える
2

abc(抽象基本クラス)を使用します。

import abc
class Resource( metaclass=abc.ABCMeta ):
    @abc.abstractproperty
    def path( self ):
        ...
        return p

次に、から継承するものResourceはすべて実装する必要がありますpathpathが実際に ABC に実装されていることに注意してください。でこの実装にアクセスできますsuper

于 2010-08-19T08:46:23.143 に答える
1

直接インスタンス化できる場合Resourceは、それを実行して、パスとgetメソッドを直接貼り付けます。

from types import MethodType

book = Resource()
def get(self):
    return aBook
book.get = MethodType(get, book)
book.path = path

これは、 and がメソッド内で使用されておらず、パスがクラスメソッドによって使用されていないことpathget前提__init__Resourceしています。

Book非クラスから何も継承されないようにすることが主な関心事である場合は、このメタクラスを使用できます

class Terminal(type):
    classes = []
    def __new__(meta, classname, bases, classdict):
        if [cls for cls in meta.classes if cls in bases]:
            raise TypeError("Can't Touch This")
        cls = super(Terminal, meta).__new__(meta, classname, bases, classdict)
        meta.classes.append(cls)
        return cls

class Book(object):
    __metaclass__ = Terminal

class PaperBackBook(Book):
    pass

スローされた例外をより適切なものに置き換えることができます。これは、多くのワンオフをインスタンス化している場合にのみ意味があります。

CPython を使用していて、それだけでは不十分な場合は、いつでも次のハッカーを試すことができます。

class Resource(object):
    def __init__(self, value, location=1):
        self.value = value
        self.location = location

with Object('book', Resource, 1, location=2):
    path = '/books/{id}'
    def get(self):
        aBook = 'abook' 
        return aBook

print book.path
print book.get()

私の最初のコンテキストマネージャーによって可能になりました。

class Object(object):
    def __init__(self, name, cls, *args, **kwargs):
        self.cls = cls
        self.name = name
        self.args = args
        self.kwargs = kwargs

    def __enter__(self):
        self.f_locals = copy.copy(sys._getframe(1).f_locals)

    def __exit__(self, exc_type, exc_val, exc_tb):
        class cls(self.cls):
            pass
        f_locals = sys._getframe(1).f_locals
        new_items = [item for item in f_locals if item not in self.f_locals]
        for item in new_items:
            setattr(cls, item, f_locals[item])
            del f_locals[item] # Keyser Soze the new names from the enclosing namespace
        obj = cls(*self.args, **self.kwargs)
        f_locals[self.name] = obj # and insert the new object      

もちろん、上記の 2 つのソリューションのいずれか、または Katrielalex の ABC の提案のいずれかを使用することをお勧めします。

于 2010-08-19T09:09:10.750 に答える