Потому что staticmethod
s не могут быть вызваны. Это дескрипторы , которые возвращают вызываемый объект при доступе через точку (.
). Класс не существует до тех пор, пока после не выполнится тело класса. В то же время это пространство имен, похожее на модуль, но с немного другими правилами области видимости. После выполнения тела пространство имен сбрасывается в __dict__
объекта класса и отбрасывается. Так что это работает.
class A:
def f(a): return a*a
v = f(2)
f = staticmethod(f)
>>> A.v
4
>>> A.f(2)
4
Это также работает
class A:
@staticmethod
def f(a): return a*a
v = f.__get__(...)(2)
Многоточие ничего не значит. @staticmethod
__get__()
не использует свой аргумент. (Это не может быть None
, или он ожидает другого аргумента. Но у нас пока нет ни класса, ни экземпляра, чтобы дать его.)
Не удалось инициализировать список / словарь по какой-то причине:
Это связано с "немного другими правилами определения области действия", о которых я упоминал ранее.
Понимания компилируются как генераторы - функции, содержащие yield
, Так что это не получится по тем же причинам:
class A:
def f(a): return a*a
xs=[2,3,4]
def comp(it):
for i in it:
yield f(i)
ys=list(comp(xs))
Помните, что я сказал, что пространство имен тела отбрасывается. Обычно методы вызываются после выполнения тела класса. Таким образом, методы компилируются для поиска имен, которые не определены локально в пространстве имен global , вместо пространства имен тела класса временного , которое, вероятно, больше не существует. Можно сохранить это временное пространство имен где-нибудь, если оно вам понадобится, например,
class A:
def f(a): return a*a
lst=[2,3,4]
global ns
ns = locals()
lst2=[ns['f'](v) for v in lst]
>>> A.lst2
[4, 9, 16]
Вы также можете выполнять вычисления старомодным способом, чтобы избежать компиляции генераторов. :
class A:
def f(a): return a*a
lst=[2,3,4]
lst2=[]
for v in lst: lst2.append(f(v))
dct={}
for v in lst: dct[f(v)] = v
Или вы можете подождать, пока у вас не появится объект класса для работы (временное пространство имен было сброшено в __dict__
объекта, поэтому они доступны как attrs):
class A:
@staticmethod
def f(a): return a*a
lst = [2, 3, 4]
A.lst2 = [A.f(v) for v in A.lst]