1

Say I have a json file look like:

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

I'd like to create an abstract base class (ABC), where the name of abstract methods are the keys of the json above, i.e.:

from abc import ABCMeta, abstractmethod class MyABC(metaclass=ABCMeta): @abstractmethod def foo(self): pass @abstractmethod def bar(self): pass 

The problem is the json file actually has lots of keys. I wonder if there's any way like:

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 

Thanks for the suggestions from the comments, but somehow it doesn't work as expected. Here is what I tried:

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 
6
  • @Nair I'd say more a duplicate of stackoverflow.com/questions/533382/… Commented Oct 24, 2019 at 9:22
  • 1
    @ChatterOne, I agree that the link and it is closely duplicate then what I mentioned. Commented Oct 24, 2019 at 9:23
  • 1
    The way a decorator works is by calling it on the function. func = decorator(function) is the same as @decorator def func(): pass. Use setattr by calling abstractmethod(method). Commented Oct 24, 2019 at 9:30
  • Try ... instead of pass. ... is called Ellipsis. Commented Oct 24, 2019 at 10:11
  • @DiptangsuGoswami Thank you, but that doesn't work quite as expected. Would you please see my edits above and show me what I did wrong? Commented Oct 24, 2019 at 10:26

1 Answer 1

0

This may work :

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 

It will correctly throw an error if you try to instantiate MyABC, or a subclass of MyABC that doesn't implement the abstract methods.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. But as my edits above show, if you define a new class like class MyClass(MyABC): pass, you can initiate MyClass() without triggering any errors. This should not be right, should it?
Why should it trigger an error according to you ? Do you actually want it to trigger an error or are you just expecting it ?
As PEP 3119 indicates, there should be TypeError because MyClass has methods that have not been implemented. "The abc module also defines a new decorator, @abstractmethod, to be used to declare abstract methods. A class containing at least one method declared with this decorator that hasn't been overridden yet cannot be instantiated."
Hey @ytu, I have edited my answer with a new solution that I think works as you intend. If so, could you please mark it as accepted ?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.