1204

組み込み関数がどのように機能するかを理解したいと思いますproperty。私を混乱させるのはproperty、デコレーターとしても使用できることですが、組み込み関数として使用する場合にのみ引数を取り、デコレーターとして使用する場合には使用しません。

この例はドキュメントからのものです:

class C:
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x
    def setx(self, value):
        self._x = value
    def delx(self):
        del self._x
    x = property(getx, setx, delx, "I'm the 'x' property.")

propertyの引数は、、、getxおよびドキュメント文字列です。setxdelx

以下のコードでpropertyは、デコレータとして使用されています。そのオブジェクトはx関数ですが、上記のコードでは、引数にオブジェクト関数の場所がありません。

class C:
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

x.setterこの場合、デコレータとデコレータはどのようにx.deleter作成されますか?

4

14 に答える 14

292

ドキュメントには、読み取り専用プロパティを作成するための単なるショートカットであると書かれています。そう

@property
def x(self):
    return self._x

と同等です

def getx(self):
    return self._x
x = property(getx)
于 2013-06-26T20:52:51.733 に答える
152

@property実装方法の最小限の例を次に示します。

class Thing:
    def __init__(self, my_word):
        self._word = my_word 
    @property
    def word(self):
        return self._word

>>> print( Thing('ok').word )
'ok'

それ以外の場合wordは、プロパティではなくメソッドのままです。

class Thing:
    def __init__(self, my_word):
        self._word = my_word
    def word(self):
        return self._word

>>> print( Thing('ok').word() )
'ok'
于 2017-02-15T00:46:29.630 に答える
90

最初の部分は単純です:

@property
def x(self): ...

と同じです

def x(self): ...
x = property(x)
  • propertyこれは、getter だけでを作成するための単純化された構文です。

次のステップは、setter と deleter を使用してこのプロパティを拡張することです。そして、これは適切な方法で起こります:

@x.setter
def x(self, value): ...

x古いものと指定されたセッターからすべてを継承する新しいプロパティを返します。

x.deleter同じように動作します。

于 2013-06-26T20:53:15.073 に答える
0

別の例を次に示します。

##
## Python Properties Example
##
class GetterSetterExample( object ):
    ## Set the default value for x ( we reference it using self.x, set a value using self.x = value )
    __x = None


##
## On Class Initialization - do something... if we want..
##
def __init__( self ):
    ## Set a value to __x through the getter / setter... Since __x is defined above, this doesn't need to be set...
    self.x = 1234

    return None


##
## Define x as a property, ie a getter - All getters should have a default value arg, so I added it - it will not be passed in when setting a value, so you need to set the default here so it will be used..
##
@property
def x( self, _default = None ):
    ## I added an optional default value argument as all getters should have this - set it to the default value you want to return...
    _value = ( self.__x, _default )[ self.__x == None ]

    ## Debugging - so you can see the order the calls are made...
    print( '[ Test Class ] Get x = ' + str( _value ) )

    ## Return the value - we are a getter afterall...
    return _value


##
## Define the setter function for x...
##
@x.setter
def x( self, _value = None ):
    ## Debugging - so you can see the order the calls are made...
    print( '[ Test Class ] Set x = ' + str( _value ) )

    ## This is to show the setter function works.... If the value is above 0, set it to a negative value... otherwise keep it as is ( 0 is the only non-negative number, it can't be negative or positive anyway )
    if ( _value > 0 ):
        self.__x = -_value
    else:
        self.__x = _value


##
## Define the deleter function for x...
##
@x.deleter
def x( self ):
    ## Unload the assignment / data for x
    if ( self.__x != None ):
        del self.__x


##
## To String / Output Function for the class - this will show the property value for each property we add...
##
def __str__( self ):
    ## Output the x property data...
    print( '[ x ] ' + str( self.x ) )


    ## Return a new line - technically we should return a string so it can be printed where we want it, instead of printed early if _data = str( C( ) ) is used....
    return '\n'

##
##
##
_test = GetterSetterExample( )
print( _test )

## For some reason the deleter isn't being called...
del _test.x

基本的に、代わりに x を使用していることを除いて、C( object ) の例と同じです... また、__init で初期化しません- ... まあ..そうしますが、__x は一部として定義されているため、削除できます。クラスの....

出力は次のとおりです。

[ Test Class ] Set x = 1234
[ Test Class ] Get x = -1234
[ x ] -1234

そして、 initで self.x = 1234 をコメントアウトすると、出力は次のようになります。

[ Test Class ] Get x = None
[ x ] None

そして、ゲッター関数で _default = None を _default = 0 に設定した場合 (すべてのゲッターにはデフォルト値が必要ですが、これまで見てきたプロパティ値によって渡されないため、ここで定義できます。デフォルトを一度定義してどこでも使用できるため、実際には悪くありません)つまり、 def x( self, _default = 0 ):

[ Test Class ] Get x = 0
[ x ] 0

注: getter ロジックは、値が操作されることを保証するために値を操作するためだけに存在します - print ステートメントについても同じです...

注:私はLuaに慣れており、単一の関数を呼び出すと10以上のヘルパーを動的に作成でき、プロパティを使用せずにPython用に同様のものを作成しましたが、ある程度機能しますが、関数は以前に作成されていましたが使用されていても、作成される前に呼び出されるという問題がまだ時々ありますが、それはそのようにコーディングされていないため奇妙です...私はLuaメタテーブルの柔軟性と、実際のセッター/ゲッターを使用できるという事実を好みます基本的に変数に直接アクセスするのではなく... ただし、Python を使用していくつかのものをすばやく構築できることは気に入っています。たとえば、GUI プログラムです。私が設計しているものは、多くの追加ライブラリなしでは不可能かもしれませんが、AutoHotkey でコーディングすると、必要な dll 呼び出しに直接アクセスでき、Java、C#、C++ でも同じことができます。

注: このフォーラムのコード出力は壊れています - コードを機能させるには、コードの最初の部分にスペースを追加する必要がありました - コピー/貼り付けの際に、すべてのスペースをタブに変換してください.... 10,000 行のファイルの場合、ファイルサイズはスペースを含めて 512KB から 1MB、タブを含めて 100KB から 200KB になり、ファイルサイズの大幅な違いと処理時間の短縮に相当します...

タブはユーザーごとに調整することもできます。つまり、2 つのスペース幅、4 つ、8 つ、または何でも好きな場合は、目の不自由な開発者に配慮したものになります。

注: フォーラム ソフトウェアのバグのため、クラスで定義されているすべての関数が適切にインデントされていません。コピー/貼り付けする場合は必ずインデントしてください。

于 2018-08-07T11:08:27.873 に答える