2009-08-29 8 views
2

Python 2.6.2でルックアップテーブルを含むクラスを作成しています。ほとんどの場合、テーブルにはデータが含まれているほど単純です。いくつかのケースはより複雑で、私は機能を呼び出せるようにしたい。しかし、私は関数を参照するいくつかのトラブルに走っています。Pythonのクラスリストのクラスメソッドを参照しています

ここではいくつかのサンプルコードです:

class a: 
    lut = [1, 
      3, 
      17, 
      [12,34], 
      5] 

lutは静的であり、同様に一定であると期待されています。

、今、私は次の操作を実行するためにWAN:

class a: 
    def spam0(self): 
     return (some_calculation_based_on_self) 

    def spam1(self): 
     return (a_different_calculation_based_on_self) 

    lut = [1, 
      3, 
      17, 
      [12,34], 
      5, 
      self.spam0 
      self.spam1] 

self.spam0self.spam1が定義されていないので、これはコンパイルされません。私はa.spamを使ってみましたが、それも未定義です。 lut[5]self.spamへの参照を返すように設定するにはどうすればよいですか?

編集:これは私が行う予定です:

class aの定義を継続): インポートは、だから私は、単純な値を返すか、いくつかを実行するかしたい

# continue to somewhere in the definition of class a 

def __init__(self, param): 
    self.param = param 

def eggs(self): 
    tmp = lut[param] 
    if (insect.isfunction(tmp)): # if tmp is self.spam() 
     return tmp()    # should call it here 
    return tmp 

を検査余分なコードは、パラメータによって異なります。

編集:lutはクラスプロパティである必要はありませんが、方法spam0spam1は、クラスメンバにアクセスする必要がないので、彼らはクラスに属する必要があります。

これを行うには、これが最善の方法であるかどうかはわかりません。私はまだこの作業を進めています。

+0

ご質問をお聞かせください。私たちの大半は、あなたが必要とするものを理解していないようです... – giorgian

+0

オブジェクトが構築されたときにパラメータが提供されるので、これは賢明ではありません。 "lut"ビジネスは '__init__'で実行され、最終的な値が計算されます。 "eggs"メソッドは、 '__init__'で計算された値を返す単純なプロパティです。あなたのデザインは不完全でなければなりません。より完全なコードスニペットを提供してください。 –

+0

問題をよりよく理解するために、さらに多くの質問があります。1)「静的」でない、つまり、インスタンスの寿命中に変更されますか? 2)メンバーはメソッドをバインドする必要があるか、単純な関数にすることができますか? 3)クラスプロパティでなければならない? 4)どのバージョンのpythonについて話していますか? 5)これは、あなたがしなければならないことを達成するための唯一の/最良の方法だと確信していますか? – giorgian

答えて

0

トリビアル:

class a: 
    @classmethod 
    def spam(cls): 
     # not really pass, but you get the idea 
     pass 

    lut = [1, 
      3, 
      17, 
      [12,34], 
      5, 
      spam] 


assert a().lut[-1] == a.spam 
assert a.spam() is None 
+0

、 'a()。lut [-1]'をクラスメソッドと呼ぶには? –

+1

'a'の中で' self.lut [-1](self) 'と呼ぶことができます。それが私のトリックです。 –

-1

a.lutの定義をaの定義の外に移動する必要があります。

class a(): 
    def spam():pass 

a.lut = [1,2,3,a.spam] 

これについて考えると、これは理にかなっています。 selfは実際にはパラメータ "self"を使用するクラスメソッドに対してのみ定義されているため、selfを使用することはできません。 selfはPythonでは特別な意味を持ちません。予約語ではありません。バインドされたクラスメソッドに渡される従来の引数ですが、this、またはfooなど、任意のものを指定することもできます。

aの定義がまだ完全ではないため、a.lutを参照すると機能しません。 Pythonは、コードのその時点でどのようなことが分かっていますか? aのクラス定義の範囲では、a自体は未定義です。

+0

この解決策(後でインスタンスxのlutを使って関数を呼び出すために)では、私が提案するアプローチのように 'a.lut [-1](x)'が必要であることに注意してください。 'a.spam'ここではバインドされていないメソッドと私は使用している関数を追加の機能を提供していない、ちょうど追加のエラーチェック。 –

+0

@Alexの場合、a.lut [-1](x)としてスパムを呼び出す必要はありません。私はOPがa.lutを繰り返して呼び出し可能なものを呼ぶ可能性が高いと考えました。このアプローチでは、不快な設計誤差があるかもしれません。あるいは、彼の問題を非常にうまくモデル化するかもしれません。実際に判断するには十分な情報がありません。 – Triptych

4

クラス本体では、クラスを作成しています。 selfはありませんので、明らかにまだself.anythingを参照することはできません。しかし、その体の中には、まだaはありません。クラス本体が完成した後に名前aがバインドされます。したがって、それはあまり明らかではありませんが、クラスaの本体では、まだa.anythingを参照することはできません。

あなたが参照できるものは、すでにバインドされているクラス属性の裸の名前です。たとえば、リストlutの末尾に5, spam]を単純に使用できます。 spamは、ある時点であなたが望むと言っているように、関数として存在します。メソッドとしてではなく、最も確実にクラスメソッドとしてではありません(classmethodはあなたのコードのどこにもありません)なぜ、あなたは明示的に組み込みの関数classmethodを直接ラップしないかぎり、私はあなたの "クラスメソッド"の使用が実際にクラスメソッドの型を参照しているとは思えません(確かに混乱します;-))。

したがって、後でxaのインスタンスでその関数を呼び出す必要がある場合は、たとえば、 a.lut[-1](x)、明示的に引数があります。

もしあなたが何か微妙なことをする必要があれば、処理中に様々なポイントでバインドされたメソッドまたはバインドされていないメソッドを得ることができます(クラスの作成が完了した後、特定のインスタンスがインスタンス化されます)。しかし、あなたがしたいことが何であるかを明確かつ完全に説明するわけではありません。私たちがこの後期の選択肢について非常に詳細なヘルプを提供するためです。

+0

私は実際には 'classmethod' *がPythonで何であるのか分かりませんので、それを参照することはできません。 :-) –

2

あなたはクラスのスコープ内にある間、あなただけの

class A: 
    def spam(self): 
     pass 

    lut = [1, 2, 3, spam] 

a = A() 
print a.lut 

を書くことができ、これはあなたのルックアップテーブルの機能であることではないことを忘れないでください

[1, 2, 3, <function spam at 0xb7bb764c>] 

を与えますあなたが意図した通りの数字。別の問題を解決したいと思うかもしれません。

+0

私は実際には数字ではなく機能を求めています。この場合、関連するパラメータで関数を呼び出します。 –

+0

はい、これは私の言いたいことです。 '' a.lut [3] 'をメソッド呼び出しとして使用するにはどうすればいいですか? a.lut [3]()は機能しません。 –

+0

'lut'を' __getitem__'を定義するクラスのインスタンスにすることはできますが、問題を解決したいとは思いません。私は別の質問を開いて、あなたの問題をより広い意味で説明することをお勧めします。 –

0

質問が分かりません。これはあなたが意味することですか?

class a: 
    lut = [1, 
      3, 
      17, 
      [12,34], 
      5] 

    def __init__(self): 
     self.lut.append(self.spam) 

    def spam(self, a): 
     print "this is %s" % a 

b = a() 
b.lut[-1](4) 

"this is 4"と表示されます。

+0

これは私の言いたいことです。コンストラクタではなく* lut []の定義の一部としてこれを行う方法がありますか? –

+0

Otto Allmendingerがこれを行う方法を示しています。http://stackoverflow.com/questions/1351669/referencing-class-methods-in-class-lists-in-python/1351694#1351694 –

+0

いいえ、オットーの答えはあなたに与えますバインドされたメソッドではなくバインドされていないメソッドなので、このようには動作しません。あなたは 'b.lut [-1](b、4)'と呼ぶ必要がありますが、これは厄介です。 –

0

あなたは関数がクラスにバインドすることにしたいです。答えのどれもこれに対処していないようです。

これは自動的には行われません。あなたがこれを行うとき:

class a: 
    def spam(self): print self 
    lut = [1, spam] 

lut[1]はスパム自体がオブジェクトに、ではないバインドされたメソッドであるので、あなたは、単にlut[1]()を呼び出すことはできません。 lut[1](self)に電話する必要があります。

直接呼び出すことのできる関数をリストに含めることが特に必要な場合は、バインドする関数を配置する必要があります。つまり、クラスではなくインスタンスから関数を参照する必要があります。これを行うには、あなたはおそらく__init__からこのリストを初期化したいと思います:

class a: 
    def spam(self): print self 
    def __init__(self): 
     self.lut = [1, self.spam] 

、今self.lut[1]()それがバインドされた方法なので、正しいです。

これは、他の機能を他の目的のためにリストに配置したり、他のオブジェクトにバインドしたり、パラメータを期待しないなどの利点があります。

インスタンス間でリストを再利用しないという欠点があります。これはあなたにとって重要かもしれません。

1

Pythonには静的なものや定数がないことに注意してください。ちょっと読んでみましょう。オブジェクトあたりlutのキャッシュバージョンを生成する例を次に示します。

class A(object): 
    def __init__(self): 
     self.__cached_lut = None 

    def spam0(self): 
     return (some_calculation_based_on_self) 

    def spam1(self): 
     return (a_different_calculation_based_on_self) 

    @property 
    def lut(self): 
     if self.__cached_lut is None: 
      self.__cached_lut = [1, 
       3, 
       17, 
       [12,34], 
       5, 
       self.spam0() 
       self.spam1()] 
     return self.__cached_lut 

a = A() 
print a.lut 
+0

しかし、この場合私はクラスをインスタンス化するたびに 'spam0'と' spam1'の両方を呼び出しています。これらは非常に時間のかかる機能です(実際は私の例です)。 ところで、 '@ property'はどういう意味ですか? –

関連する問題