আমি প্রায়শই নিজেকে কমান্ড লাইন ইউটিলিটিগুলি লিখতে পাই যেখানে প্রথম যুক্তিটি বিভিন্ন শ্রেণীর একটিতে বোঝায়। উদাহরণস্বরূপ ./something.py feature command —-arguments, Featureকোন শ্রেণিটি কোথায় এবং commandসেই শ্রেণীর একটি পদ্ধতি। এখানে একটি বেস ক্লাস যা এটি সহজ করে তোলে।
ধারণাটি হ'ল এই বেস ক্লাসটি তার সমস্ত সাবক্লাসের পাশাপাশি একটি ডিরেক্টরিতে থাকে। তারপরে আপনি কল করতে পারবেন ArgBaseClass(foo = bar).load_subclasses()যা কোনও অভিধানে ফিরে আসবে। উদাহরণস্বরূপ, ডিরেক্টরিটি যদি এর মতো দেখায়:
- arg_base_class.py
- feature.py
feature.pyপ্রয়োগগুলি ধরে নিলে class Feature(ArgBaseClass), তারপরে উপরের অনুরোধটি load_subclassesফিরে আসবে { 'feature' : <Feature object> }। একই kwargs( foo = bar) Featureক্লাসে পাস করা হবে ।
#!/usr/bin/env python3
import os, pkgutil, importlib, inspect
class ArgBaseClass():
# Assign all keyword arguments as properties on self, and keep the kwargs for later.
def __init__(self, **kwargs):
self._kwargs = kwargs
for (k, v) in kwargs.items():
setattr(self, k, v)
ms = inspect.getmembers(self, predicate=inspect.ismethod)
self.methods = dict([(n, m) for (n, m) in ms if not n.startswith('_')])
# Add the names of the methods to a parser object.
def _parse_arguments(self, parser):
parser.add_argument('method', choices=list(self.methods))
return parser
# Instantiate one of each of the subclasses of this class.
def load_subclasses(self):
module_dir = os.path.dirname(__file__)
module_name = os.path.basename(os.path.normpath(module_dir))
parent_class = self.__class__
modules = {}
# Load all the modules it the package:
for (module_loader, name, ispkg) in pkgutil.iter_modules([module_dir]):
modules[name] = importlib.import_module('.' + name, module_name)
# Instantiate one of each class, passing the keyword arguments.
ret = {}
for cls in parent_class.__subclasses__():
path = cls.__module__.split('.')
ret[path[-1]] = cls(**self._kwargs)
return ret