0

次のようにインスタンス化できるボタンクラスがあります。

engine.createElement((0, 0), Button(code=print, args=("Stuff!",)))

クリックすると「Stuff!」と表示されます。ただし、ボタンがクリックされるたびにボタンが破壊される必要があります。このようなもの:

engine.createElement((0, 0), Button(code=engine.killElement, args=(self,)))

ただし、その時点で self は呼び出し元を参照しているため、それは呼び出し元を殺すだけです。私がする必要があるのは、事前にクラスに独自の「自己」を与えることです...

クリック時に文字列が変数を'self'参照するようにすることだけを考えましたが、引数selfで文字列を使用したい場合はどうすればよいでしょうか?'self'

これを行う方法は何ですか?私のアーキテクチャはすべて間違っていますか?

4

4 に答える 4

3

残念ながら、これは不可能です。ボタンのコンストラクターへの引数は、コンストラクターが評価される前に評価されます。ボタンを変数に割り当ててから、コールバックを設定する必要があります。

b = Button(code=engine.killElement)
b.args = (b, )

または似たようなもの。

于 2012-11-20T22:44:57.600 に答える
2

オブジェクトを作成するにはオブジェクトへの参照が必要になるように基本的に設定しましたが、これはもちろん不可能です。次のようなことができます (リストは引数のアンパックのタプルと同じくらい良いです):

arglist = []
button = Button(code=engine.killElement, args=arglist)
arglist.append(button)
engine.createElement((0, 0), button)

これは洗練されておらず、不明瞭で冗長ですが、インスタンスへの参照をインスタンスに取得します。

別のポスターが提案したように、センチネル値を使用できます。selfおそらく、指定された関数の最初の引数として常に渡され、明示的に指定する必要のない規則 (Python 自体など) を単純に使用することをお勧めします。次に、コールバックはself、何もしない場合でも、常に take を使用するように記述されます。

ただし、通常は、オブジェクトのコンストラクターに渡すことによってオブジェクトの動作を指定するのではなく、継承によって指定します。つまり、 をサブクラス化し、そのメソッドなどをオーバーライドして、サブクラス をインスタンス化します。それがどのインスタンスに接続されているかを知っていることは問題ではありません。だから私はイエスの側に降りてきます、あなたのアーキテクチャは少し間違っています。ButtononClickonClick

于 2012-11-20T22:51:00.847 に答える
1

これは一般的に不可能です。

ただし、Buttonクラスを作成している場合は、「自分自身」を意味する特別なセンチネル値を渡すことができます。例えば:

class Button(object):
    yourself = 'yourself'
    def __init__(self, code, args):
        self.code = code
        self.args = [self if arg is yourself else arg for arg in args]

それで:

engine.createElement((0, 0), Button(code=engine.killElement, args=(Button.yourself,)))

適切なセンチネルを選択するのは難しい場合がありますNone。 、0、 またはなどの明白な選択''は正当な値である可能性があり、思いついたトリッキーなものでさえ、デバッグ中に有用な引数であることが判明する場合があります。モジュール内でクラス変数またはグローバルを作成yourselfするということは、センチネルを再定義する必要が生じた場合に、センチネルを使用するすべての場所ではなく、1 か所だけ変更する必要があることを意味します。

適切なセンチネル値の選択に関する簡単な説明については、http://bytes.com/topic/python/answers/555169-sentinel-values-special-casesを参照してください。より詳しい情報が掲載された別のブログがありますが、簡単な検索では見つかりませんでした…とにかく、簡単なアイデアをいくつか紹介します。

  1. Noneそれが機能する場合、常に最良の答えです。
  2. センチネルとなる空のクラスを定義します。クラス オブジェクトまたはクラス オブジェクトの任意のインスタンスを使用できます。
  3. クラスのグローバル インスタンスを作成しますobject( object())。
  4. 空の関数を定義し、それを使用します (またはその関数などfunc_code)。
  5. Ellipsis(またはtype(Ellipsis)という名前の型ですが、その名前にアクセスすることはできません) は、 と の友人 (およびおそらくそれらに渡すオブジェクトの定義)ellipsisでのみ使用されるため、ほとんどの場合安全です。__getitem__slice
  6. 有効な値ではない可能性のある型があり、既にインスタンスが存在する場合func_codeは、関数のメンバーなど、それらのいずれかを使用し__init__ます。
于 2012-11-20T22:48:13.173 に答える
0

たぶん、次のようなものが役立ちます:

class Button(object):
    def __new__(cls, *args, **kwargs):
        obj = object.__new__(cls, *args, **kwargs)
        kwargs['args'].append(obj)
        return obj

    def __init__(self, code, args):
        self.code = code
        self.args = args

    def click(self):
        return self.code, self.args

b = Button(code="engine.killElement", args=[])
print b.click()

出力:

('engine.killElement', [<__main__.Button object at 0x00B59AF0>])    
于 2012-11-21T17:34:25.793 に答える