Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在同一类的方法中使用类/静态方法作为默认参数值_Python_Decorator_Default Value_Class Method_Static Methods - Fatal编程技术网

Python 在同一类的方法中使用类/静态方法作为默认参数值

Python 在同一类的方法中使用类/静态方法作为默认参数值,python,decorator,default-value,class-method,static-methods,Python,Decorator,Default Value,Class Method,Static Methods,我想这样做: class SillyWalk(object): @staticmethod def is_silly_enough(walk): return (False, "It's never silly enough") def walk(self, appraisal_method=is_silly_enough): self.do_stuff() (was_good_enough, reason) = appra

我想这样做:

class SillyWalk(object):
    @staticmethod
    def is_silly_enough(walk):
        return (False, "It's never silly enough")
    def walk(self, appraisal_method=is_silly_enough):
        self.do_stuff()
        (was_good_enough, reason) = appraisal_method(self)
        if not was_good_enough:
            self.execute_self_modifying_code(reason)
        return appraisal_method
    def do_stuff(self):
        pass
    def execute_self_modifying_code(self, problem):
        from __future__ import deepjuju
        deepjuju.kiss_booboo_better(self, problem)
因为有人能做到

>>> silly_walk = SillyWalk()
>>> appraise = walk()
>>> is_good_walk = appraise(silly_walk)
同时也有一些神奇的机器学习发生;最后一点我并不特别感兴趣,它只是我想到的第一件事,作为在函数内上下文和从调用方的角度演示静态方法使用的一种方式

无论如何,这是行不通的,因为
够傻了
实际上并不是一个函数:它是一个对象,它的
\u get\u
方法将返回原始的
够傻了
函数。这意味着它仅在作为对象属性引用时以“正常”方式工作。有问题的对象是由
staticmethod()
函数创建的,装饰程序将该函数放在
SillyWalk
足够傻了
属性和最初使用该名称定义的函数之间

这意味着,为了从
SillyWalk.walk
或其调用者中使用
evaluation\u method
的默认值,我们必须

  • 调用
    evaluation\u方法。获取(实例,所有者)(…)
    而不是只调用
    evaluation\u方法(…)
  • 或者将其指定为某个对象的属性,然后将该对象属性引用为一个方法,我们称之为
    evaluation\u method
考虑到这两种解决方案似乎都不是特别好的™, 我想知道是否有更好的方法来获得这种功能。我基本上想要一种方法来指定一个方法,默认情况下,应该使用在同一个类的范围内定义的特定类或静态方法来执行其日常例程的某些部分。

我不希望使用
None
,因为我希望允许
None
传递不应调用该特定函数的消息。我想我可以使用一些其他的值,比如
False
NotImplemented
,但似乎a)hackety b)不得不额外编写几行代码,以及其他冗余文档,对于一些似乎可以非常简洁地表示为默认参数的内容,这似乎很烦人


做这件事的最佳方法是什么?

不确定我是否得到了您想要的东西,但使用getattr会更干净吗

>>> class SillyWalk(object):
    @staticmethod
    def ise(walk):
        return (False, "boo")
    def walk(self, am="ise"):
        wge, r = getattr(self, am)(self)
        print wge, r


>>> sw = SillyWalk()
>>> sw.walk("ise")
False boo
我最终编写了一个(un)包装函数,用于函数定义头中,例如

def walk(self, appraisal_method=unstaticmethod(is_silly_enough)):
这似乎真的管用,至少它让我的博士学位没有通过就中断了

这是:

def unstaticmethod(static):
    """Retrieve the original function from a `staticmethod` object.

    This is intended for use in binding class method default values
      to static methods of the same class.

    For example:
        >>> class C(object):
        ...     @staticmethod
        ...     def s(*args, **kwargs):
        ...         return (args, kwargs)
        ...     def m(self, args=[], kwargs={}, f=unstaticmethod(s)):
        ...         return f(*args, **kwargs)
        >>> o = C()
        >>> o.s(1, 2, 3)
        ((1, 2, 3), {})
        >>> o.m((1, 2, 3))
        ((1, 2, 3), {})
    """
    # TODO: Technically we should be passing the actual class of the owner
    #         instead of `object`, but
    #         I don't know if there's a way to get that info dynamically,
    #         since the class is not actually declared
    #         when this function is called during class method definition.
    #       I need to figure out if passing `object` instead
    #         is going to be an issue.
    return static.__get__(None, object)
更新:
我为
非静态方法
函数本身编写了doctests;他们也通过了。我仍然不能完全确定这是否是一个真正明智的做法,但它似乎确实有效。

也许您首先需要的是使用函数(而不是方法)

class SillyWalk(object):
    def is_silly_enough(walk):
        return (False, "It's never silly enough")

    def walk(self, appraisal_function=is_silly_enough):
        self.do_stuff()
        (was_good_enough, reason) = appraisal_function(self)
        if not was_good_enough:
            self.execute_self_modifying_code(reason)
        return appraisal_function
    def do_stuff(self):
        pass
    def execute_self_modifying_code(self, problem):
        deepjuju.kiss_booboo_better(self, problem)
请注意,评估函数的默认值现在将是一个函数,而不是一个方法,即使在创建类后(在代码末尾),is_Dully_将被绑定为类方法

这意味着

>>> SillyWalk.is_silly_enough
<unbound method SillyWalk.is_silly_enough>

在定义步行之后的任何地方。

我想可能是一个解决办法。我希望能够通过传递callable来覆盖缺省值,并且我还希望缺省值是最快的。“ise”是静态方法的名称,这一点也不太明显。我想我正在寻找一个名为
uncorate\u static\u method
的函数。我想我可以编写,并将其包含在我想要使用此模式的每个模块中。。为了能够使
def
def行走(self,am=uncorate\u static\u method(ise)):
+1这与我的想法非常接近。不过,我更多地考虑了一般情况,
is\u dully\u walk
会像典型的静态方法一样,不接受实例类型的参数。我想我可以在声明
walk
之后做一些类似
is\u-silly\u-ough=staticmethod(functools.partial(is\u-silly\u-ough,None))
的事情来提供无关的参数,这样外部调用方就不必这样做了。我想缺点是函数签名将不再作为准确的文档。对不起,最后的评论没有意义。如果将
staticmethod(…)
调用放在使用static作为默认参数值的函数声明之后,那么这将非常有效。谢谢。有人能评论一下这个答案和OP(下面)的答案之间的利弊吗?我发布了一个关于它的问题,但没有答案。。。谢谢我认为OP使用的是英语意义上的“方法”,而不是OOP意义上的“方法”,即“评估方法”变成了“评估方法”,因此无需称之为评估函数。
>>> SillyWalk.walk.im_func.func_defaults[0] # the default argument to .walk
<function is_silly_enough at 0x0000000002212048>
    is_silly_enough = staticmethod(is_silly_enough)