Я согласен, что это довольно странное поведение. Возможно, есть причина для этого; возможно, это один из тех угловых случаев, который так и не был полностью расследован, или, если он расследовался, считался настолько неясным, что его не стоит рассматривать. Иногда случается.
Если вы хотите, чтобы поведение, назначающее функцию в качестве атрибута класса, всегда делало ее статическим методом, вы можете сделать это с метаклассом.
class func2static(type):
def __setattr__(cls, name, value):
if type(value) is type(lambda: 0):
value = staticmethod(value)
type.__setattr__(cls, name, value)
class X(object):
__metaclass__ = func2static
Теперь давайте покажем, что как классу, так и экземплярам класса может быть назначена функция, которая затем вызывается.
f = lambda x: x
X.f = f
X.f(3) # no exception
x = X()
x.g = f
x.g(3) # also no exception
Это на самом деле не решает проблему, если вы, к сожалению, используете патчи для случайных классов, определенных в других модулях, но вам, вероятно, не следует этого делать. : -)