1

私はPythonでクラスを作成し始めていますが、用語について非常に混乱しているため、質問の仕方がわからないため、質問への回答が見つかりません。したがって、この投稿の二重タイトルです。次のコードを使用して、質問の仕方がわからないという質問を明確にしようとします。

単純なクラス内にメソッドを作成したい:

class SimpleClass:
    add(self,Value)
        #Magic goes here

SC=SimpleClass()

このメソッドは、クラスに新しい変数を追加するのと同等である必要があります。

SC.NewVariableInsideTheClass="test"

ただし、メソッドを介して、たとえば:

SC.NewVariableInsideTheClass.add("test")

どちらの場合も、「NewVariableInsideTheClass」は以前は存在しなかったため、クラス内で初めてその変数を作成しています。

したがって、メソッドは最初に存在しないインスタンスを作成し(クラス内の変数の名前だと思います)、その値を「テスト」に設定する必要がありますが、その方法を実際に見つけたり検索したりできません.. .

私が必要とするものに対する正しい質問はどれですか??

どうもありがとうございました!

- - - - - - - - - 編集 - - - - - - - - - - -

わかりましたので、私がやりたいことは、実行時に同じ結果を得ることです:

SC.NewVariableInsideTheClass.add("test")

そして行うとき:

SC.NewVariableInsideTheClass.add("test")

ただし、どちらもクラスの外で実行する必要があり、「NewVariableInsideTheClass」が初めて使用されます。ここでの目的は、クラスを変数ストレージとして使用することです。たとえば、変数が初めて使用されるときに何かが発生し、既に存在する場合 (SC.NewVariableInsideTheClass の形式で)、別の方法で使用できるようになります。 . これが今より具体的であることを願っています...

2 番目の編集; 理由 -------------------------

うわー、あなたの回答の質と詳細に感銘を受けました。とても感謝しています! 私がこれを望む理由を知っていただきたいです: 私は簡単な Python スクリプト IDE を作成しています (現在は主に Python の学習用であり、まだ役に立ちません)。したがって、コードの基本は、途中で新しい変数を作成することです。プログラムは関数も作成するため、変数を作成して処理するための最初の解決策は、作成されたプログラム内のすべての変数をグローバルにし、新しい関数ごとにそれらを再度呼び出すことでした。そのコードは醜いので、クラスを学習して使用することにしましたが、変数はプログラムごとに異なるため、関数の作成を標準化したい (つまり、最初の関数かどうかを知る必要はなく、初期化する必要がある場合)変数、または既に存在する場合)、次のことができるようにする方法: -新しい変数が存在しない場合でも、変数という名前のリストに、簡単にアクセスできる名前で保存します -リスト内の新しい項目として新しい値で以前の変数を拡張できる -それらを取得できる値 グローバルを使用せずに、このソリューションに出くわしました。実際に私はあなたのコードを変更しました。今はあなたのコードを使用していますが、「追加」という名前の代わりに「追加」という名前を付けたので、自由に行うことができます:

SC.NewVar.append('これは新しい値です') SC.NewVar.append('これは新しい値です')

そして、最初は作成されますが(存在しないため)、2回目に新しい値が追加されるため、それを呼び出したり、再生したり、自動生成された他の関数から使用したりできます-コード:)

4

2 に答える 2

4

免責事項:なぜこれをしたいのかわかりません。を使用して属性を動的に作成する場合は、setattr十分なはずです。

SC = SimpleClass()
setattr(SC, 'your_new_attribute_name', 'test')

とにかく、ヘルパー クラスを使用して必要なものを取得する簡単な方法があります。

In [1]: class SimpleClass:
   ...:     def __getattr__(self, attr):
   ...:         return AttributeSetter(self, attr)
   ...: class AttributeSetter:
   ...:     def __init__(self, inst, attr):
   ...:         self._inst = inst
   ...:         self._attr = attr
   ...:     def add(self, value):
   ...:         setattr(self._inst, self._attr, value)
   ...:         

In [2]: SC = SimpleClass()

In [3]: SC.new_attr.add('test')

In [4]: SC.new_attr
Out[4]: 'test'

あなたのコメントについて。次のように書くことが可能かどうかを尋ねる場合SimpleClass

SC.new_attr

呼び出しを呼び出した後、文字列 'test' とを返します。Sc.new_attr.add('test')

SC.new_attr.add('other')

そのようなものです:

SC.new_attr

が文字列 を返すようになった'other'場合、答えは「いいえ、不可能です」です。

以下が を生成しないようなクラスを書くことは不可能です:AttributeError

In [2]: SC = SimpleClass()

In [3]: SC.new_attr.add('test')
In [4]: SC.new_attr   #this returns a string, not a user-defined class
'test'

In [5]: SC.new_attr.add('new value')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-f218074b7a68> in <module>()
----> 1 SC.new_attr.add('new value')

AttributeError: 'str' object has no attribute 'add'

なぜ聞くのですか?さて、インタプリタが実際に何をするか見てみましょ:

In [5]: import dis
   ...: dis.dis(lambda: SC.new_attr.add('some string'))
   ...: 
  2           0 LOAD_GLOBAL              0 (SC) 
              3 LOAD_ATTR                1 (new_attr) 
              6 LOAD_ATTR                2 (add) 
              9 LOAD_CONST               1 ('some string') 
             12 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             15 RETURN_VALUE 

モジュールを使用するdisと、インタープリターが実行しているバイトコードを確認できます。2 つ異なる LOAD_ATTRバイトコードがあることに注意してください。ご覧のとおり、インタープリターは最初にnew_attr属性を取得し、その後、完全に独立した操作として属性を取得しaddます。

現在、クラスSCは最初の属性アクセス (つまり へのアクセス) の動作のみを変更できますnew_attr。次のバイトコードが にアクセスすることを知る方法がないaddため、設定された文字列を返すことが賢明な唯一の方法です。

次の属性アクセス は、取得した値に対してadd実行されます。これは、明らかに存在しない文字列の属性をインタープリターが探すことを意味します。add

これを回避する唯一の方法AttributeErrorは、メソッドを持つオブジェクトを返すことですがadd、これは次のことを意味します。

In [6]: SC.new_attr
Out[6]: 'test'

文字列を返す代わりに別のオブジェクトを返すため、失敗します。"test"

addこれを回避するには、メソッドと属性を持つオブジェクトを返すことで、value次のようになります。

In [12]: SC.new_attr
Out[12]: <__main__.TheClass at 0x7fac44727a90>

In [13]: SC.new_attr.value
Out[13]: 'test'

In [14]: SC.new_attr.add('other')

In [15]: SC.new_attr.value
Out[15]: 'other'

別の解決策は、このクラスを文字列のように動作するように記述することです (サブクラス化することもできますstrが、実行しないでください!組み込みのサブクラス化は決して正しいことではありません。正確な結果を知らずに実行すると、問題発生し、それらを見つけて解決するのが難しくなります)、しかしこれは、コードがより複雑になり、文字列がサポートするすべての操作を実装しなければならないことを意味します (つまり、約 80-90-100 メソッドを実装することを意味します!)

于 2013-07-16T09:17:09.730 に答える