Создайте ABC с абстрактными методами, определенными из ключей JSON - PullRequest
1 голос
/ 24 октября 2019

Скажем, у меня есть файл json, похожий на:

{
    "foo": ["hi", "there"],
    "bar": ["nothing"]
}

Я хотел бы создать абстрактный базовый класс (ABC), где имена абстрактных методов являются ключами json выше, т.е. :

from abc import ABCMeta, abstractmethod

class MyABC(metaclass=ABCMeta):

    @abstractmethod
    def foo(self):
        pass

    @abstractmethod
    def bar(self):
        pass

Проблема в том, что файл json на самом деле имеет много ключей. Интересно, есть ли что-то вроде:

import json

with open("the_json.json") as f:
    the_json = json.load(f)

class MyABC(metaclass=ABCMeta):

    # for k in the_json.keys():
    #     create abstract method k

Спасибо за предложения из комментариев, но почему-то все работает не так, как ожидалось. Вот что я попробовал:

class MyABC(metaclass=ABCMeta):
    pass

def f(self):
    pass

setattr(MyABC, "foo", abstractmethod(f))
# I also tried
# setattr(MyABC, "foo", abstractmethod(lambda self: ...))

# Try to define another class that inherits MyABC
class MyClass(MyABC):
    pass

c = MyClass()
# Now this should trigger TypeError but it doesn't
# I can even call c.foo() without getting any errors

1 Ответ

0 голосов
/ 24 октября 2019

Это может работать:

from abc import ABCMeta, abstractmethod

with open("the_json.json") as f:
    the_json = json.load(f)

class MyABC(metaclass=ABCMeta):

    def func(self):
        pass

    for k in the_json:
        locals()[k] = abstractmethod(func)

# Delete attribute "func" is a must
# Otherwise it becomes an additional abstract method in MyABC
delattr(MyABC, "func")
delattr(MyABC, "f")
delattr(MyABC, "k")

class MyClass(MyABC):
    pass

MyClass()
# TypeError: Can't instantiate abstract class MyClass with abstract methods bar, foo

Будет правильно выдано сообщение об ошибке, если вы попытаетесь создать экземпляр MyABC или подкласс MyABC, который не реализует абстрактные методы.

...