__init__ in python 类 中可以使用静态方法作为默认参数吗?
Can you use a static method as default parameter in __init__ in python classes?
我正在为神经网络写一个 class,我想给它一些定制形式,这样你就可以选择不同的成本函数和正则化。为此,我想将它们设置为 __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
可以工作,但 class 似乎不存在。那么,最后一次,为什么?
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__
我猜??
您将静态方法用作默认参数时遇到问题的原因是两个问题的结合。
第一个问题是,当def
语句是运行 时,需要明确定义默认参数,而不仅仅是在调用函数时。这是因为默认参数内置到函数对象中,而不是每次函数 运行s 时都重新计算(这与为什么像空列表这样的可变默认参数通常是错误的原因相同)。无论如何,这就是为什么不能使用 MyClass.static_method
作为默认参数的原因,因为在定义函数时 MyClass
尚未定义(毕竟 class 对象只是创建的它的内容已经创建。
下一个问题是 staticmethod
对象不具有与常规函数相同的所有属性和方法。通常这无关紧要,因为当您通过 class 对象(例如 MyClass.static_method
一旦 MyClass
存在)或通过实例(例如 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__
.
的代码版本不同
我正在为神经网络写一个 class,我想给它一些定制形式,这样你就可以选择不同的成本函数和正则化。为此,我想将它们设置为 __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
可以工作,但 class 似乎不存在。那么,最后一次,为什么?
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__
我猜??
您将静态方法用作默认参数时遇到问题的原因是两个问题的结合。
第一个问题是,当def
语句是运行 时,需要明确定义默认参数,而不仅仅是在调用函数时。这是因为默认参数内置到函数对象中,而不是每次函数 运行s 时都重新计算(这与为什么像空列表这样的可变默认参数通常是错误的原因相同)。无论如何,这就是为什么不能使用 MyClass.static_method
作为默认参数的原因,因为在定义函数时 MyClass
尚未定义(毕竟 class 对象只是创建的它的内容已经创建。
下一个问题是 staticmethod
对象不具有与常规函数相同的所有属性和方法。通常这无关紧要,因为当您通过 class 对象(例如 MyClass.static_method
一旦 MyClass
存在)或通过实例(例如 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__
.