4

クラスCを宣言していて、いくつかの宣言が非常に似ているとします。fこれらの宣言のコードの繰り返しを減らす関数を使用したいと思います。fいつものように宣言して使用することができます:

>>> class C(object):
...     def f(num):
...             return '<' + str(num) + '>'
...     v = f(9)
...     w = f(42)
... 
>>> C.v
'<9>'
>>> C.w
'<42>'
>>> C.f(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method f() must be called with C instance as first argument (got int instance instead)

おっとっと!私はうっかりf外の世界にさらされてしまいましたが、それはself議論を必要としません (そして、明らかな理由でできません)。1つの可能性はdel、私がそれを使用した後の関数です:

>>> class C(object):
...     def f(num):
...             return '<' + str(num) + '>'
...     v = f(9)
...     del f
... 
>>> C.v
'<9>'
>>> C.f
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'C' has no attribute 'f'

fしかし、宣言後に後でもう一度使用したい場合はどうすればよいですか? 関数を削除しても意味がありません。私はそれを「非公開」にして (つまり、その名前の前に を付けて__)処理することもできますが、異常なチャネルを介してオブジェクトを@staticmethod呼び出すと非常にファンキーになります。staticmethod

>>> class C(object):
...     @staticmethod
...     def __f(num):
...             return '<' + str(num) + '>'
...     v = __f.__get__(1)(9)   # argument to __get__ is ignored...
... 
>>> C.v
'<9>'

staticmethod記述子であるオブジェクト自体は呼び出し可能ではないため、上記の狂気を使用する必要があります。staticmethodオブジェクトを呼び出す前に、オブジェクトによってラップされた関数を回復する必要があります。

これを行うためのより良い方法が必要です。クラスで関数をきれいに宣言し、宣言中に使用し、後でクラス内から使用するにはどうすればよいですか? 私もこれをしなければなりませんか?

4

6 に答える 6

14

簡単に言えば、解決策は f がクラスのメンバーである必要がないということです。私は、あなたの思考プロセスが Javaish 言語フィルターを通過してメンタル ブロックを引き起こしていると推測しています。次のようになります。

def f(n):
    return '<' + str(num) + '>'

class C(object):

    v = f(9)
    w = f(42)

その後、 f を再度使用したい場合は、それを使用してください

>>> f(4)
'<4>'

この話の教訓は、「Python では、すべてをクラスに強制する必要はない」ということだと思います。

于 2008-11-20T08:50:18.190 に答える
3

Ali Aの答えを拡張すると、モジュールの名前空間で f を本当に避けたい場合 (_f のようなエクスポートされていない名前を使用するか、 __all__ を設定するだけでは不十分)、クロージャ内にクラスを作成することでこれを達成できます。 .

def create_C():
    def f(num):
        return '<' + str(num) + '>'

    class C(object):
        v = f(9)
        def method_using_f(self, x):  return f(x*2)
    return C

C=create_C()
del create_C

このようにして、C はその定義とメソッド内で f にアクセスできますが、他には何もアクセスできません (そのメソッドのかなり複雑なイントロスペクションを除いて ( C.method_using_f.im_func.func_closure)) 。

ただし、これはおそらくほとんどの目的にとってやり過ぎです-「_」接頭辞の命名規則を使用して f が内部であることを文書化することで、通常は十分です。

[編集] もう 1 つのオプションは、使用したいメソッドで事前にラップされた関数オブジェクトへの参照を保持することです。たとえば、デフォルトの引数として設定します。

class C(object):
    def f(num):
        return '<' + str(num) + '>'

    v = f(9)
    def method_using_f(self, x, f=f):  return f(x*2)

    del f

(クロージャーアプローチの方がおそらく良いと思いますが)

于 2008-11-20T12:00:16.200 に答える
2

私はあなたがこれをやろうとしていると信じています:

class C():
...     class F():
...         def __call__(self,num):
...             return "<"+str(num)+">"
...     f=F()
...     v=f(9)
>>> C.v
'<9>'
>>> C.f(25)
'<25>'
>>> 

たぶん、より良いまたはより多くのpythonicソリューションがあります...

「クラスで関数を宣言し、宣言中に使用し、後でクラス内から使用する」

ごめん。できません。

「できない」はPythonとうまくいかないようです

于 2008-11-20T13:09:46.683 に答える
1

これは 1 つの可能性です。

class _C:
    # Do most of the function definitions in here
    @classmethod
    def f(cls):
        return 'boo'

class C(_C):
    # Do the subsequent decoration in here
    v = _C.f()
于 2008-11-20T11:37:17.777 に答える
1

1つのオプション:より良いものを書くstaticmethod

class staticfunc(object):
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kw):
        return self.func(*args, **kw)
    def __repr__(self):
        return 'staticfunc(%r)' % self.func
于 2008-11-20T23:21:16.373 に答える
0

最初から始めましょう。

「クラスで関数を宣言し、宣言中に使用し、後でクラス内から使用する」

ごめん。できません。「クラス内」は「宣言中に使用」と矛盾します。

  • In a class は、宣言の一部として作成されたことを意味します。
  • 宣言中に使用すると、クラスの外に存在することを意味します。多くの場合、メタ クラスとして。ただし、他の方法もあります。

Cw と Cv がどうあるべきかは明確ではありません。それらは単なる文字列ですか?その場合、外部関数fが最適なソリューションです。「名前空間を乱雑にしない」というのは少し怪しいです。やはり、また利用したいものです。

C と同じモジュールに入っています。そのため、Python にはモジュールがあります。関数とクラスを結合します。

import myCmod

myCmod.C.w
myCmod.C.v
myCmod.f(42)

w と v が単純な文字列でない場合、多くの柔軟性を提供する非常に優れたソリューションがあります。

一般に、このようなクラスレベル (「静的」) 変数には、他のクラスを使用できます。目的の API を完全に実現することはできませんが、これは近いです。

>>> class F(object):
    def __init__( self, num ):
        self.value= num
        self.format= "<%d>" % ( num, )

>>> class C(object):
    w= F(42)
    v= F(9)

>>> C.w
<__main__.F object at 0x00C58C30>
>>> C.w.format
'<42>'
>>> C.v.format
'<9>'

この利点は、F が拡張可能な適切な第一級のものであることです。露出を避けようとしている「隠された」ものではありません。これは現実のことなので、オープン/クローズの原則に従い、それを拡張できるようにすることもできます。

于 2008-11-20T12:15:14.627 に答える