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

一般来说,这不是一个好主意,因为当人们(包括六个月后的你)阅读代码时,他们会期望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

由于类是对象,您可以通过添加属性来扩展它们,然后在属性查找期间可以找到这些属性。确保您执行此操作一次(例如,在导入另一个文件期间)。

这是一个真实的例子:

>>> 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 回答