简体   繁体   中英

How can I extend a class instance?

I have the following code, which is a command line test

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()

Is there a possibility to extend the App class with extra functions? I know there is the following solution

class App2(App):
     ....   

app = App2()
app.cmdloop()

but in my case I would like to run only the App and extend it if it is possible.

In general this is not a good idea, because when people (including you in six months) read the code they will expect App to be the class they know about, and for an extended version of the class to have a different name. However, there's nothing preventing you from naming the subclass the same as the original:

class App(App):
    # etc.

Python's smart enough to know that the App in parentheses means the one it already knows about, and then, since the new class has the same name, it replaces the original one. Don't worry, the new class contains a reference to the old one, so the old class doesn't go away entirely (if it did, nothing inherited by the subclass would work).

If the class came from some module that you've imported, you can even monkey-patch the replacement class back into the original module, so that all code that imports that module uses your replacement class. (Though I would recommend against it!)

import appmodule

class App(appmodule.App):
    # etc.

appmodule.App = App

Of course, this gets tricky, because some modules may already have imported a reference to the original class, if you don't do this first thing in your script. And if other modules are also trying to patch the same class, all hell can break loose. Still, if you want to confuse yourself and those who will maintain your code, Python will let you do it!

It is worth noting that you can always augment the class dictionary, therefore extending it at runtime.

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')

You have to think how python does lookups at runtime. First looks at the instance of yourclass , then looks at the __mro__ (starting with type(yourclass) ), and on up until it gets to object .

Since classes ARE objects, you can extend them by adding attributes, which will then be found during attribute lookups. Make sure you do this ONCE (eg, during an import of another file).

Here is a real example:

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

this isnt an exact solution but it allows you to always access it by App name

rename App class to _App

then where you want to use it

from blah import _App as App

and when you extend it

from blah import App2 as App

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM