Вот очень простой Base
класс, который содержит статический метод и метод класса:Как проверить, является ли метод методом класса или статическим методом в метаклассе?
class Base():
@staticmethod
def f():
print("Base.f")
@classmethod
def g(cls):
print("Base.g")
def h(self):
print("Base.h")
Если класс должен быть производным от Base
и переопределить либо f
или g
то, что staticmethod
и classmethod
декораторы должны для повторного использования в методах переопределения.
class A(Base):
@staticmethod
def f():
print("A.f")
class B(Base):
@classmethod
def g(cls):
print("B.g")
Итак, сначала я думал, что я хотел бы создать метакласс, который автоматически делает f
в staticmethod
и g
staticmethod
.
class BaseMeta(type):
def __init__(cls, name, bases, namespace):
super().__init__(name, bases, namespace)
if 'f' in namespace: cls.f = staticmethod(cls.f)
if 'g' in namespace: cls.g = classmethod(cls.g)
Теперь остальные классы не должны использовать staticmethod
и classmethod
явно.
class Base(metaclass=BaseMeta):
def f():
print("Base.f")
def g(cls):
print("Base.g")
def h(self):
print("Base.h")
class A(Base):
def f():
print("A.f")
class B(Base):
def g(cls):
print("B.g")
Это работает, но мне не нравится, как он выглядит. Теперь я понимаю, что staticmethod
и classmethod
декораторы должны явно использоваться (в конце концов, явно лучше, чем неявное, не так ли?)
Так я думал, что я мог держать метакласса, но на этот раз вместо того, чтобы , применяя декораторов, я должен был только проверить независимо от того, были ли они использованы и выбрасывали исключение, если они этого не сделали.
class BaseMeta(type):
def __init__(cls, name, bases, namespace):
super().__init__(name, bases, namespace)
# check if cls.f is a static method
if not inspect.isfunction(cls.f):
raise Exception("f should be a static method")
# check if cls.g is a static method
if not (inspect.ismethod(cls.g) and cls.g.__self__ == cls):
raise Exception("g should be a class method")
К сожалению, это не работает. Похоже, что в metaclasse __init__
все считается просто функцией (просто печать cls.f
и cls.g
делает это очевидным).
Есть ли что-то, что мне не хватает здесь?
В явном ядре Python не обязательно \ обязательно \ лучше, чем неявное. Подумайте, что EAFP (проще попросить прощения, чем разрешение) считается Pythonic и мышление более высокого уровня поощряется в деталях вычислений в качестве примеров. – GRAYgoose124