1

@property具体的なクラスで使用してゲッターを定義する際に問題があります。Pythonコードは次のとおりです。

from abc import ABCMeta, abstractproperty

class abstract(object):
    __metaclass__ = ABCMeta

    def __init__(self, value1):
        self.v1 = value1

    @abstractproperty
    def v1(self):
        pass

class concrete(abstract):
    def __init__(self, value1):
        super(concrete, self).__init__(value1)

    @property
    def v1(self):
        return self.v1

次に、コードをテストして、次のエラーを取得します。

test_concrete = concrete("test1")
test_concrete.v1

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-190-eb896d7ec1c9> in <module>()
----> 1 test_concrete = concrete("test1")
      2 test_concrete.v1

<ipython-input-189-bf15021022d3> in __init__(self, value1)
     11 class concrete(abstract):
     12     def __init__(self, value1):
---> 13         super(concrete, self).__init__(value1)
     14 
     15     @property

<ipython-input-189-bf15021022d3> in __init__(self, value1)
      3 
      4     def __init__(self, value1):
----> 5         self.v1 = value1
      6 
      7     @abstractproperty

AttributeError: can't set attribute

v1基本的には読み取り専用属性に設定するつもりです。

属性とそのゲッター関数に同じ名前を使用することに慣れていますが、クラスが抽象クラスから継承された場合、それはできないようです。

ゲッター関数に別の名前を使用することで回避策を見つけましv1get_v1

class abstract(object):
    __metaclass__ = ABCMeta

    def __init__(self, value1):
        self.v1 = value1

    @abstractproperty
    def get_v1(self):
        pass

class concrete(abstract):
    def __init__(self, value1):
        super(concrete, self).__init__(value1)

    @property
    def get_v1(self):
        return self.v1

この問題のより良い回避策はありますか?

4

1 に答える 1

2

あなたの問題は、抽象クラスとは何の関係もありません。これは名前空間の問題です。プロパティ オブジェクトとインスタンス属性は同じ名前空間を占有します。インスタンス属性とプロパティの両方にまったく同じ名前を使用することはできません。

を使用してプロパティにアクセスしようとしていますが、インスタンスのメソッドからアクセスしているという理由だけで、魔法のようにインスタンス属性ではありません。これは常にプロパティ オブジェクトになります。self.v1 = ...v1

同じように、プロパティ ゲッターは無限ループを引き起こします。

@property
def v1(self):
    return self.v1

インスタンス属性ではなく、プロパティオブジェクトであるためself.v1 です。

実際のストレージには別の名前を使用します。

def __init__(self, value1):
    self._v1 = value1

@property
def v1(self):
    return self._v1

Python では (C# や Java のように) 完全にプライベートな属性を持つことはできないことに注意してください。名前の先頭のアンダースコアは単なる慣例であり、決定されたコーダーは常にインスタンスの状態に直接アクセスできます。オブジェクトはこれpropertyを変更しません。

于 2015-08-12T10:02:59.340 に答える