简体   繁体   English

覆盖python中方法的内部函数

[英]Overriding an inner function of a method in python

That is a kind of best practices question. 这是一种最佳实践问题。

I have a class structure with some methods defined. 我有一个类结构,定义了一些方法。 In some cases I want to override a particular part of a method. 在某些情况下,我想覆盖方法的特定部分。 First thought on that is splitting my method to more atomic pieces and override related parts like below. 首先想到的是将我的方法拆分为更多原子碎片并覆盖相关部分,如下所示。

class myTest(object):
    def __init__(self):
        pass

    def myfunc(self):
        self._do_atomic_job()
        ...
        ...

    def _do_atomic_job(self):
        print "Hello"

That is a practical-looking way to solve the problem. 这是一种解决问题的实用方法。 But since I have too many parameters that is needed to be transferred to and revieced back from _do_atomic_job() , I do not want to pass and retrieve tons of parameters. 但是由于我有太多的参数需要转移到_do_atomic_job()并从中恢复,我不想传递和检索大量的参数。 Other option is setting these parameters as class variables with self.param_var etc but those parameters are used in a small part of the code and using self is not my preferred way of solving this. 其他选项是使用self.param_var等将这些参数设置为类变量,但这些参数在代码的一小部分中使用,并且使用self不是我解决此问题的首选方法。

Last option I thought is using inner functions. 我认为最后一个选项是使用内部函数。 (I know I will have problems in variable scopes but as I said, this is a best practise and just ignore them and think scope and all things about the inner functions are working as expected) (我知道我会在变量范围内遇到问题,但正如我所说,这是一种最佳实践,只是忽略它们并认为范围和内部函数的所有内容都按预期工作)

class MyTest2(object):
    mytext = ""

    def myfunc(self):
        def _do_atomic_job():
            mytext = "Hello"
        _do_atomic_job()
        print mytext

Lets assume that works as expected. 让我们假设按预期工作。 What I want to do is overriding the inner function _do_atomic_job() 我想要做的是重写内部函数_do_atomic_job()

class MyTest3(MyTest2):
    def __init__(self):
        super(MyTest3, self).__init__()
        self.myfunc._do_atomic_job = self._alt_do_atomic_job  # Of course this do not work!

    def _alt_do_atomic_job(self):
        mytext = "Hollla!"

Do what I want to achieve is overriding inherited class' method's inner function _do_atomic_job 做我想要实现的是重写继承的类'方法的内部函数_do_atomic_job

Is it possible? 可能吗?

Either factoring _do_atomic_job() into a proper method, or maybe factoring it into its own class seem like the best approach to take. _do_atomic_job()分解为正确的方法,或者将其分解为自己的类似乎是最好的方法。 Overriding an inner function can't work, because you won't have access to the local variable of the containing method. 覆盖内部函数不起作用,因为您将无法访问包含方法的局部变量。

You say that _do_atomic_job() takes a lot of parameters returns lots of values. 你说_do_atomic_job()需要很多参数才能返回很多值。 Maybe you group some of these parameters into reasonable objects: 也许您将其中一些参数分组到合理的对象中:

_do_atomic_job(start_x, start_y, end_x, end_y) # Separate coordinates
_do_atomic_job(start, end)                     # Better: start/end points
_do_atomic_job(rect)                           # Even better: rectangle

If you can't do that, and _do_atomic_job() is reasonably self-contained, you could create helper classes AtomicJobParams and AtomicJobResult . 如果你不能这样做,并且_do_atomic_job()是合理自包含的,你可以创建帮助类AtomicJobParamsAtomicJobResult An example using namedtuples instead of classes: 使用namedtuples而不是类的示例:

AtomicJobParams = namedtuple('AtomicJobParams', ['a', 'b', 'c', 'd'])

jobparams = AtomicJobParams(a, b, c, d)
_do_atomic_job(jobparams)                # Returns AtomicJobResult

Finally, if the atomic job is self-contained, you can even factor it into its own class AtomicJob . 最后,如果原子作业是自包含的,您甚至可以将其分解为自己的AtomicJob类。

class AtomicJob:
    def __init__(self, a, b, c, d):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self._do_atomic_job()

    def _do_atomic_job(self):
        ...
        self.result_1 = 42
        self.result_2 = 23
        self.result_3 = 443

Overall, this seems more like a code factorization problem. 总的来说,这似乎更像是代码分解问题。 Aim for rather lean classes that delegate work to helpers where appropriate. 瞄准相当精益的课程,在适当的时候将工作委托给帮助者。 Follow the single responsibility principle . 遵循单一责任原则 If values belong together, bundle them up in a value class. 如果值属于一起,请将它们捆绑在一个值类中。

As David Miller (a prominent Linux kernel developer) recently said : 正如David Miller(着名的Linux内核开发人员) 最近所说

If you write interfaces with more than 4 or 5 function arguments, it's possible that you and I cannot be friends. 如果您编写的接口包含4个或5个以上的函数参数,那么您和我可能无法成为朋友。

Inner variables are related to where they are defined and not where they are executed. 内部变量与它们的定义位置有关,而与它们的执行位置无关。 This prints "hello". 这打印“你好”。

class MyTest2(object):
    def __init__(self):
        localvariable = "hello"
        def do_atomic_job():
            print localvariable
        self.do_atomic_job = do_atomic_job

    def myfunc(self):
        localvariable = "hollla!"
        self.do_atomic_job()


MyTest2().myfunc()

So I can't see any way you could use the local variables without passing them, which is probably the best way to do it. 因此,我无法看到任何方式可以使用局部变量而不传递它们,这可能是最好的方法。

Note: Passing locals() will get you a dict of the variables, this is considered quite bad style though. 注意:传递locals()会得到一个变量的字典,但这被认为是相当糟糕的风格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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