3

new.instancemethod を使用して、関数 (aFunction) をあるクラス (A) から別のクラス (B) のインスタンスに割り当てたいと考えています。aFunction を取得して B のインスタンスに適用できるようにする方法がわかりません。aFunction は A のインスタンスで実行されることを期待しているため、現在エラーが発生しています。

[注: 私が使用しているクラス (私の例では B) は型キャストをサポートしていないため、__class__ 属性を使用してインスタンスを A にキャストすることはできません]

import new

class A(object):
    def aFunction(self):
        pass

#Class which doesn't support typecasting
class B(object): 
    pass

b = B()
b.aFunction = new.instancemethod(A.aFunction, b, B.__class__)
b.aFunction()

これはエラーです:

TypeError: unbound method aFunction() must be called with A instance as first argument (got B instance instead)
4

5 に答える 5

6

new.instancemethod関数を取ります。A.aFunctionバインドされていないメソッドです。それは同じことではありません。A().aFunction(理解を助けるために、関連するすべてのもの(<code> A.aFunction()など)とそれらのタイプを表示するために、一連のprintステートメントを追加してみてください。)

記述子がどのように機能するかを理解していないと思います。厄介な詳細のすべてを学びたくない場合、実際に起こっていることはaFunction、クラス定義内の宣言が関数から非データ記述子を作成することです。これは、アクセス方法に応じて、バインドされていないメソッド(A.aFunction)またはバインドされたメソッド()を取得することを意味する魔法のようなものですA().aFunction

に変更aFunctionすると@staticmethod、これは実際に機能します。静的メソッドの場合、A.aFunctionA().aFunctionは単なる関数だからです。(これが標準によって真であることが保証されているかどうかはわかりませんが、他の誰かがそれを実装する方法を理解するのは難しいです。)しかし、「aFunctionがBのインスタンスにそれ自体を適用できるようにする」場合は、静的メソッドは役に立ちません。

基礎となる関数を実際に取得したい場合は、いくつかの方法があります。記述子がどのように機能するかを理解するのに役立つ限り、これが最も明確だと思います。

f = object.__getattribute__(A, 'aFunction')

一方、最も単純なのはおそらく次のとおりです。

f = A.aFunction.im_func

次に、呼び出しnew.instancemethodは、その関数をクラスBのインスタンスの通常のメソッドとして呼び出すことができる記述子に変換する方法です。

b.aFunction = new.instancemethod(f, b, B)

大量のデータを印刷すると、状況がより明確になります。

import new

class A(object):
  def aFunction(self):
    print self, type(self), type(A)

#Class which doesn't support typecasting
class B(object): 
    pass

print A.aFunction, type(A.aFunction)
print A().aFunction, type(A().aFunction)
print A.aFunction.im_func, type(A.aFunction.im_func)
print A().aFunction.im_func, type(A().aFunction.im_func)

A.aFunction(A())
A().aFunction()

f = object.__getattribute__(A, 'aFunction')
b = B()
b.aFunction = new.instancemethod(f, b, B)
b.aFunction()

次のようなものが表示されます。

<unbound method A.aFunction> <type 'instancemethod'>
<bound method A.aFunction of <__main__.A object at 0x108b82d10>> <type 'instancemethod'>
<function aFunction at 0x108b62a28> <type 'function'>
<function aFunction at 0x108b62a28> <type 'function'>
<__main__.A object at 0x108b82d10> <class '__main__.A'> <type 'type'>
<__main__.A object at 0x108b82d10> <class '__main__.A'> <type 'type'>
<__main__.B object at 0x108b82d10> <class '__main__.B'> <type 'type'>

これが示さない唯一のことは、バインドされたメソッドとバインドされていないメソッドを作成する魔法です。そのためには、を調べる必要がありA.aFunction.im_func.__get__ます。その時点で、記述子を自分で掘り下げようとするよりも、記述子のハウツーを読む方がよいでしょう。

最後にもう1つ、brandizziが指摘したように、これはほとんどやりたくないことです。代替手段は次のとおりです。メソッドではなく無料の関数として記述します。そのため、;aFunctionを呼び出すだけです。b.aFunction()実際の作業を行う関数を除外し、それを持ってA.aFunction呼び出すB.aFunctionだけです。B集計してA転送します。等

于 2012-09-27T19:15:45.587 に答える
1

私はあなたが尋ねた質問への回答をすでに投稿しました。new.instancemethodしかし、問題を解決するために理解する必要があるというレベルまで降りる必要はありませんでした。起こった唯一の理由は、あなたが間違った質問をしたからです。質問すべき内容とその理由を見てみましょう。

PySide.QtGui では、リスト ウィジェットのアイテムにフォントと色を設定するメソッドが必要ですが、そうではないようです。

これはあなたが本当に欲しいものです。これを行う簡単な方法があるかもしれません。もしそうなら、それはあなたが望む答えです。また、ここから始めることで、「本当は何をしたいの?」というコメントを避けることができます。または、「これがあなたがやろうとしていることに対して適切であるとは思えません」(多くの場合、反対票を投じるか、さらに重要なことに、潜在的な回答者があなたの質問を無視するだけです)。

もちろん、メソッドにする代わりに、QListWidgetItem を受け取る関数を作成してその関数を呼び出すこともできますが、_ _.

うまくいかない理由があると思います。でもなかなかいいのが思いつきません。コードのどの行がこれを言ったとしても:

item.setColor(color)

代わりに次のように言います。

setItemColor(item, color)

とてもシンプルです。

たとえば、項目がバインドされた色設定デリゲートを渡す必要がある場合でも、関数を使用するとメソッドを使用する場合と同じくらい簡単です。これの代わりに:

delegate = item.setColor

これは:

delegate = lambda color: setItemColor(item, color)

したがって、これをメソッドにする必要がある正当な理由がある場合は、それを説明する必要があります運が良ければ、あなたが間違っていたことがわかります。そして、あなたがしようとしていたことよりも、あなたがやりたいことをするためのはるかに簡単な方法があります。

これを行う明白な方法は、PySide でクラスまたはファクトリ関数を指定できるようにすることです。これにより、QListWidgetItem サブクラスを記述でき、これまでに扱ったすべてのリスト項目がそのサブクラスのインスタンスになります。しかし、私はそれを行う方法を見つけることができません。

これは、PySide の機能であるべきもののようです。その場合は、知りたいと思うでしょう。そうでない場合、そしてあなたもコメント者も回答者も、それが悪い設計である、または実装が難しいという正当な理由を思いつかない場合は、機能要求を提出する必要があります。それは次のバージョンに含まれる可能性があります. (これは、現在のバージョンに対して来週コードをリリースする必要がある場合に役立つというわけではありませんが、それでもやる価値はあります。)

それを行う方法が見つからなかったので、setColorメソッドをQListWidgetItemクラスに追加する方法を見つけようとしましたが、何も思いつきませんでした。

モンキー パッチ クラスは非常に単純です。

QListWidgetItem.setColor = setItemColor

これができることを知らなかったとしても、それは問題ありません。それがあなたがやろうとしていることだと人々が知っていれば、彼らは最初にこれを提案するでしょう。(わかりました、おそらく多くの Python プログラマーはモンキー パッチについてよく知っているわけではありませんが、記述子や について知っている人の数よりもはるかに多いのnew.instancemethodです。)より良い答え。

これを知っていたとしても、一部の拡張モジュールではそれができません。試して失敗した場合は、代わりに何がうまくいかなかったかを説明してください。

PySide では、メソッドをクラスに追加できません。モンキーパッチをやってみると、_ _.

うまくいかなかった理由を誰かが知っているかもしれません。そうでない場合、少なくとも彼らはあなたが試みたことを知っています.

したがって、すべてのインスタンスに追加する必要があります。

モンキー パッチのインスタンスは次のようになります。

myListWidgetItem.setColor = setItemColor

繰り返しになりますが、迅速な回答とより良い回答が得られます。

しかし、おそらくあなたはそれを知っていて、試してみましたが、うまくいきませんでした:

PySide では、各インスタンスにメソッドを追加することもできません。やってみると、_ _.

そこで__class__、PyQt4 では機能するが、PySide では_ _.

これは PySide の仕組みに過ぎないため、おそらく何の役にも立たないでしょう。しかし、あなたが試したことは言及する価値があります。

そこで、そのカスタム サブクラスを作成し、そのメソッドをコピーすることにしまし

そして、ここまでずっと、元の質問に入力したすべてのものを配置する場所です. 問題を解決するために本当に必要な場合は、情報がそこにあります。しかし、簡単な解決策があれば、仕組みを推測しているだけの人から、混乱した答えがたくさん返ってくることはありませんnew.instancemethod

于 2012-09-28T03:28:50.710 に答える
0

可能であれば、デコレータaFunctionを使用してバインドを解除できます@staticmethod: -

class A(object):
    @staticmethod
    def aFunction(B):    # Modified to take appropriate parameter..
        pass

class B(object): 
    pass

b = B()
b.aFunction = new.instancemethod(A.aFunction, b, B.__class__)
b.aFunction()

*注: - 適切なパラメーターを取得するようにメソッドを変更する必要があります..

于 2012-09-27T18:54:40.083 に答える
-1

Rohit Jainに感謝します-これが答えです:

import new

class A(object):
    @staticmethod
    def aFunction(self):
        pass

#Class which doesn't support typecasting
class B(object): 
    pass

b = B()
b.aFunction = new.instancemethod(A.aFunction, b, B.__class__)
b.aFunction()
于 2012-09-27T18:55:36.267 に答える