如何扩展类实例?

时间:2013-02-25 21:24:00

标签: python class

我有以下代码,这是一个命令行测试

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并在可能的情况下扩展它。

3 个答案:

答案 0 :(得分:5)

一般来说,这不是一个好主意,因为当人们(包括你在六个月内)阅读代码时,他们希望App成为他们所知道的类,并且对于类的扩展版本来说有一个不同的名字。但是,没有什么可以阻止您将子类命名为与原始子类相同:

class App(App):
    # etc.

Python足够聪明地知道括号中的App表示它已经知道的那个,然后,由于新类具有相同的名称,它将替换原始类。不用担心,新类包含对旧类的引用,因此旧类不会完全消失(如果确实如此,子类继承的任何内容都不会起作用)。

如果该类来自您导入的某个模块,您甚至可以将替换类修补回原始模块,以便导入该模块的所有代码都使用您的替换类。 (虽然我会建议反对它!)

import appmodule

class App(appmodule.App):
    # etc.

appmodule.App = App

当然,这很棘手,因为如果您不在脚本中首先执行此操作,某些模块可能已经导入了对原始类的引用。如果其他模块也试图修补同一个类,那么一切都会崩溃。不过,如果你想让自己和那些维护代码的人感到困惑,那么Python会让你这么做!

答案 1 :(得分: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

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

这是一个真实的例子:

>>> class foo():
...     pass
...
>>> x = foo()
>>>
>>> # Define a function and attach it
>>>
>>> def bar(self, a):
...     print(a)
...
>>> foo.bar = bar
>>>
>>> x.bar('a')
a

答案 2 :(得分:0)

这不是一个确切的解决方案,但它允许您始终通过应用名称

访问它

将App类重命名为_App

然后你要使用它

from blah import _App as App

当你扩展它时

from blah import App2 as App