0

コマンドラインテストである次のコードがあります

from cmd2 import Cmd
class App(Cmd, object):
    def __init__(self, *args, **kwargs):
            pass

    def do_test(self, line):
        'test'
        print "parent test"


class App2():
    def __init__(self, *args, **kwargs):
            pass

    def do_test2(self, line):
        print "Test2"           


app = App()
app.cmdloop()

追加の関数でAppクラスを拡張する可能性はありますか?私は次の解決策があることを知っています

class App2(App):
     ....   

app = App2()
app.cmdloop()

Appしかし、私の場合は、とのみを実行し、可能であればそれを拡張したいと思います。

4

3 に答える 3

6

一般に、これは良い考えではありません。なぜなら、人々(6か月後のあなたを含む)がコードを読むとき、App彼らは知っているクラスであり、クラスの拡張バージョンが異なる名前を持つことを期待するからです。ただし、サブクラスに元のクラスと同じ名前を付けることを妨げるものは何もありません。

class App(App):
    # etc.

PythonはApp、括弧内がすでに知っているクラスを意味することを知っているほど賢く、新しいクラスは同じ名前であるため、元のクラスを置き換えます。心配しないでください。新しいクラスには古いクラスへの参照が含まれているため、古いクラスが完全になくなるわけではありません(もしそうなら、サブクラスに継承されたものは何も機能しません)。

クラスがインポートしたモジュールからのものである場合は、置換クラスを元のモジュールにモンキーパッチで戻すこともできます。これにより、そのモジュールをインポートするすべてのコードで置換クラスが使用されます。(私はそれに反対することをお勧めしますが!)

import appmodule

class App(appmodule.App):
    # etc.

appmodule.App = App

もちろん、これは注意が必要です。スクリプトで最初にこれを行わないと、一部のモジュールが元のクラスへの参照をすでにインポートしている可能性があるためです。また、他のモジュールも同じクラスにパッチを適用しようとすると、すべての地獄が崩壊する可能性があります。それでも、自分自身とコードを保守する人を混乱させたい場合は、Pythonでそれを実行できます。

于 2013-02-25T21:34:04.953 に答える
1

クラスディクショナリはいつでも拡張できるため、実行時に拡張できることに注意してください。

class App(...):
  def __init__(self, a, b):
    pass

  def do_something(self, a):
    pass


app_instance = App()


def do_something_else(self, b):
  pass

App.do_something_else = do_something_else


app_instance.do_something_else('b')

実行時にPythonがどのようにルックアップを行うかを考える必要があります。最初にのインスタンスをyourclass調べ、次に__mro__(で始まりtype(yourclass))を調べ、次に。に到達するまで続けobjectます。

クラスはオブジェクトであるため、属性を追加することでクラスを拡張できます。属性は、属性のルックアップ中に検出されます。必ずこれを1回実行してください(たとえば、別のファイルのインポート中)。

これが実際の例です:

>>> class foo():
...     pass
...
>>> x = foo()
>>>
>>> # Define a function and attach it
>>>
>>> def bar(self, a):
...     print(a)
...
>>> foo.bar = bar
>>>
>>> x.bar('a')
a
于 2013-02-25T22:04:34.053 に答える
0

これは正確な解決策ではありませんが、常にアプリ名でアクセスできます

Appクラスの名前を_Appに変更します

次に、それを使用したい場所

from blah import _App as App

そしてあなたがそれを拡張するとき

from blah import App2 as App
于 2013-02-25T21:32:28.340 に答える