9

単一ニューロンのシミュレーションをプログラミングしています。したがって、多くのパラメーターを処理する必要があります。ここでのアイデアは、SingleParameter 用とパラメーターの Collection 用の 2 つのクラスがあるということです。パラメータ値に簡単にアクセスし、コードを読みやすくするために、property() を使用します。これは単一のパラメーターには完璧に機能しますが、SingleParameter の後に Collection のプロパティに名前を付けたいため、コレクションに実装する方法がわかりません。ここに例があります:

class SingleParameter(object):
  def __init__(self, name, default_value=0, unit='not specified'):
    self.name = name
    self.default_value = default_value
    self.unit = unit
    self.set(default_value)
  def get(self):
    return self._v
  def set(self, value):
    self._v = value
  v = property(fget=get, fset=set, doc='value of parameter')

par1 = SingleParameter(name='par1', default_value=10, unit='mV')
par2 = SingleParameter(name='par2', default_value=20, unit='mA')

# par1 and par2 I can access perfectly via 'p1.v = ...'
# or get its value with 'p1.v'

class Collection(object):
  def __init__(self):
    self.dict = {}
  def __getitem__(self, name):
    return self.dict[name] # get the whole object
    # to get the value instead:
    # return self.dict[name].v
  def add(self, parameter):
    self.dict[parameter.name] = parameter
    # now comes the part that I don't know how to implement with property():
    # It shoule be something like
    # self.__dict__[parameter.name] = property(...) ?

col = Collection()
col.add(par1)
col.add(par2)
col['par1'] # gives the whole object

# Now here is what I would like to get:
# col.par1 -> should result like col['par1'].v
# col.par1 = 5 -> should result like col['par1'].v = 5

プロパティ()を理解するために私が入れた他の質問:

4

7 に答える 7

10

組み込み関数getattrと を見てくださいsetattr。きっとあなたはもっと幸せになれるでしょう。

于 2009-01-05T12:42:31.417 に答える
7

両方のクラスに同じ get/set 関数を使用すると、引数リストを使った厄介なハックが発生します。非常に大雑把ですが、これは私が行う方法です:

クラス SingleParameter で、通常どおり get と set を定義します。

def get(self):
  return self._s
def set(self, value):
  self._s = value

クラス Collection では、プロパティを作成するまで情報を知ることができないため、メタセット/メタゲット関数を定義し、後でラムダ関数を使用してそれらを特定します。

def metaget(self, par):
  return par.s
def metaset(self, value, par):
  par.s = value
def add(self, par):
  self[par.name] = par
  setattr(Collection, par.name,
    property(
      fget=lambda x : Collection.metaget(x, par),
      fset=lambda x, y : Collection.metaset(x,y, par))
于 2009-01-13T16:33:49.457 に答える
5

プロパティは、属性を動的に評価するか、読み取り専用にするためのものです。必要なのは、属性アクセスのカスタマイズです。__getattr__そして__setattr__それを本当にうまくやってください、そしてそれが十分でない__getattribute__場合もあります。__getattr__

詳細については、属性アクセスのカスタマイズに関する Python ドキュメントを参照してください。

于 2009-01-05T12:48:29.093 に答える
3

特性パッケージを見たことがありますか?ここでは、パラメータクラスを使用して車輪の再発明を行っているようです。トレイトには、アプリケーションのタイプに役立つ可能性のある追加機能もあります(ちなみに、ニューラルシミュレーションでトレイトを喜んで使用している人を知っています)。

于 2009-01-05T13:56:58.800 に答える
2

ここで、set-/getattr を使用してソリューションを実装しました。

class Collection(object):
...
  def __setattr__(self, name, value):
    if 'dict' in self.__dict__:
      if name in self.dict:
        self[name].v = value
    else:
      self.__dict__[name] = value
  def __getattr__(self, name):
    return self[name].v

あまり気に入らないことが 1 つあります。それは、属性が __dict__ にないことです。そして、それらもそこにあれば、値のコピーを持っているでしょう-これは危険な場合があります...

于 2009-01-05T14:10:26.700 に答える
0

最後に、property() を使用してクラスを実装することに成功しました。アドバイスありがとうございます。それを解決するのにかなりの時間を要しましたが、この演習が Python の OOP をよりよく理解するのに役立つことを約束できます。

__getattr__ と __setattr__ でも実装しましたが、プロパティソリューションの長所と短所はまだわかりません。しかし、これは別の質問に値するようです。プロパティソリューションは完全にきれいに見えます。

コードは次のとおりです。

class SingleParameter(object):
  def __init__(self, name, default_value=0, unit='not specified'):
    self.name = name
    self.default_value = default_value
    self.unit = unit
    self.set(default_value)
  def get(*args):
    self = args[0]
    print "get(): "
    print args
    return self._v
  def set(*args):
    print "set(): "
    print args
    self = args[0]
    value = args[-1]
    self._v = value
  v = property(fget=get, fset=set, doc='value of parameter')

class Collection(dict):
  # inheriting from dict saves the methods: __getitem__ and __init__
  def add(self, par):
    self[par.name] = par
    # Now here comes the tricky part.
    # (Note: this property call the get() and set() methods with one
    # more argument than the property of SingleParameter)
    setattr(Collection, par.name,
      property(fget=par.get, fset=par.set))

# Applying the classes:
par1 = SingleParameter(name='par1', default_value=10, unit='mV')
par2 = SingleParameter(name='par2', default_value=20, unit='mA')
col = Collection()
col.add(par1)
col.add(par2)
# Setting parameter values:
par1.v = 13
col.par1 = 14
# Getting parameter values:
par1.v
col.par1
# checking identity:
par1.v is col.par1
# to access the whole object:
col['par1']

私は新しいので、先に進む方法がわかりません: フォローアップの質問をどのように処理するか (これ自体のように):

  • get() が 2 回呼び出されているようです - なぜですか?
  • oop-design: プロパティ vs. "__getattr__ & __setattr__" - いつ何を使うべきですか?
  • 自分の質問に対する自分の回答を承認済みとしてチェックするのは失礼ですか?
  • 関連する質問や同じ例で詳しく説明した質問を同じコンテキストに入れるために、タイトルの名前を変更することをお勧めしますか?

プロパティ()を理解するために私が入れた他の質問:

于 2009-01-13T14:01:20.310 に答える
0

私は似たようなことをするクラスを持っていますが、コレクションオブジェクトで次のことを行いました:

setattr(self, par.name, par.v)

于 2013-03-21T18:57:09.240 に答える