如何扩展类实例?
我有以下这段代码,这是一个命令行测试
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 个回答
这不是一个完全准确的解决办法,但它可以让你通过应用的名字随时访问它。
把应用的类名改成 _App。
然后在你想用它的地方,
from blah import _App as App
当你要扩展它的时候,
from blah import App2 as App
一般来说,这样做不是个好主意,因为当人们(包括你自己在六个月后)阅读代码时,他们会期待App
是他们熟悉的那个类,而扩展版本的类应该有个不同的名字。不过,实际上你是可以把子类命名为和原类一样的名字的:
class App(App):
# etc.
Python很聪明,它知道括号里的App
指的是它已经认识的那个类,然后因为新类和原来的名字相同,它就用新类替换了原来的类。别担心,新类里有对旧类的引用,所以旧类并不会完全消失(如果真的消失了,子类继承的东西就都不管用了)。
如果这个类是从你导入的某个模块来的,你甚至可以把替换后的类“补丁”回原来的模块,这样所有导入那个模块的代码就会使用你的替换类。(不过我不推荐这样做!)
import appmodule
class App(appmodule.App):
# etc.
appmodule.App = App
当然,这样做会变得复杂,因为有些模块可能已经导入了原类的引用,如果你不在脚本的第一时间做这个操作。而且如果其他模块也在尝试修改同一个类,那就会引发一堆麻烦。不过,如果你想让自己和将来维护你代码的人感到困惑,Python会让你这么做!
值得注意的是,你可以随时增加类字典的内容,这样就可以在运行时扩展它。
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