我有以下代码,这是一个命令行测试
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
并在可能的情况下扩展它。
答案 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