1

概要

メソッドが直接呼び出されたのではなく、プロパティを介して呼び出されたかどうかを判断することは可能ですか?

詳細

一部のコードに API の変更を加えています。古い API では Getter と Setter (GetAttrSetAttr) が使用されていましたが、新しいパブリック API ではx.Attrとがx.Attr = valそれぞれ使用されます。プログラマーが呼び出したときに非推奨の警告を追加したいGetAttr()

事実上、私が探しているのはこの魔法の_was called_via_property関数です:

import warnings

class MyClass(object):
    def __init__(self):
        self._attr = None

    def GetAttr(self):
        if not _was_called_via_property():
            warnings.warn("`GetAttr()` is deprecated. Use `x.attr` property instead.", DeprecationWarning)
        return self._attr

    def SetAttr(self, value):
        if not _was_called_via_property():
            warnings.warn("deprecated", DeprecationWarning)
        self._attr = value

    Attr = property(GetAttr, SetAttr)

関数に加えてデコレータを介して物事が定義されている場合、理想的にはソリューションも機能しproperty()ますが、必須ではありません。

そのようです:

@property
def attr(self):
    if not _was_called_via_property():
       warnings.warn("deprecated", DeprecationWarning)
    return self._attr

@attr.setter
def attr(self, value):
    if not _was_called_via_property():
        warnings.warn("deprecated", DeprecationWarning)
    self._attr = value
4

2 に答える 2

2

property記述子アクセスと直接アクセスを区別することはできません。

適切なプロパティを作成し、古いメソッド プロキシを使用します。

@property
def attr(self):
    return self._attr

@property.setter
def attr(self, value):
    self._attr = value

# legacy access to the attr property
def GetAttr(self):
   warnings.warn("deprecated", DeprecationWarning)
   return self.attr

def SetAttr(self, value):
   warnings.warn("deprecated", DeprecationWarning)
   self.attr = value
于 2015-08-03T21:03:49.880 に答える
1

別の解決策は、ラップすることpropertyです:

def myprop(getter, setter):
    return property(lambda self : getter(self, True), 
                    lambda self, x : setter(self, x, True))


class MyClass(object):
    def __init__(self):
        self._attr = None

    def GetAttr(self, called_via_property=False):
        if not called_via_property:
            warnings.warn("`GetAttr()` is deprecated. Use `x.attr` property instead.", DeprecationWarning)
        return self._attr

    def SetAttr(self, value, called_via_property=False):
        if not called_via_property:
            warnings.warn("deprecated", DeprecationWarning)
        self._attr = value

    Attr = myprop(GetAttr, SetAttr)

別の解決策として、次のような警告付きの getter と setter をオーバーライド__getattr__して生成することもできます。__setattr__

class MyBase(object):
    def __getattr__(self, key):
         if key.startswith("Get"):
              tail = key[3:]
              if hasattr(self, tail):
                   def getter(self):
                        res = getattr(self, tail)
                        issue_warning()
                        return res
                   return lambda : getter(self)
         raise AttributeError

セッターについても同様です。

于 2015-08-03T21:11:30.637 に答える