你能在python类的__init__中使用静态方法作为默认参数吗



我正在为神经网络编写一个类,我想给它一些形式的自定义,这样你就可以选择不同的成本函数和正则化。为此,我想将它们设置为__init__()方法中的默认参数。但是当我在示例中传递MyClass.static_method时,解释器然后告诉我MyClass还没有定义。为什么会这样?有没有比我更好的解决方法?

当然,您可以将静态方法设置为默认参数,但随后会出现其他问题。例如,如果我想访问函数名称(我实际上想要的),我不能立即使用__name__。我知道如何用另一种方式来实现,通过访问static_method.__func__.__name__。但这似乎很笨拙,当你得到一个静态方法对象时,它似乎不打算以这种方式使用。

class MyClass:
@staticmethod
def static_method():
do_something()
def __init__(self, func=MyClass.static_method, func2=static_method):
self.name = func.__name__                  #Does not work
self.name2 = func2.__func__.__name__       #Should work

我确实希望MyClass.static_method能工作,但当时这个类似乎并不存在。最后一次,为什么?

将静态方法用作默认参数时出现问题的原因是两个问题的结合。

第一个问题是,在运行def语句时,需要很好地定义默认参数,而不仅仅是在调用函数时。这是因为默认参数被内置到函数对象中,而不是在每次函数运行时重新计算(这也是为什么像空列表这样的可变默认参数通常是错误的原因)。无论如何,这就是为什么不能使用MyClass.static_method作为默认参数的原因,因为在定义函数时还没有定义MyClass(类对象只有在创建了所有内容之后才会生成)。

下一个问题是staticmethod对象不具有与常规函数相同的所有属性和方法。通常情况下,这并不重要,因为当您通过类对象(例如,一旦MyClass存在,则为MyClass.static_method)或通过实例(例如,self.static_method)访问它时,它将是可调用的,并具有__name__。但这是因为在这些情况下,您得到的是底层函数,而不是staticmethod对象本身。staticmethod对象本身是一个描述符,但不是可调用的。

因此,这两种功能都无法正常工作:

class MyClass:
@staticmethod
def static_method():
pass
def foo(self, func=MyClass.static_method): # won't work because MyClass doesn't exist yet
pass
def bar(self, func=static_method): # this declaration will work (if you comment out foo)
name = func.__name__  # but this doesn't work when the bar() is called
func()                # nor this, as func is the staticmethod object

有效的方法是使用staticmethod对象下面的实际函数作为默认函数:

def baz(self, func=static_method.__func__):  # this works!
name = func.__name__
func()

与使用name = func.__func__.__name__的代码版本不同,当您传入其他函数(或绑定方法)时,这也会起作用。

DEFAULT = object()
class MyClass:
@staticmethod
def static_method():
do_something()
def __init__(self, func=DEFAULT, func2=DEFAULT):
self.name = self.static_method.__name__  if func is DEFAULT else func.__name__
self.name2 = self.static_method.__func__.__name__ if func2 is DEFAULT else func2.__func__.__name__

我想??

最新更新