I'd want to be able to dispatch the instantiation of a class depending of a parameter.
This has been asked here and the following answer provides a good solution, but the use of the globals()[name]() seems a bit ugly to me. Also, I understand how it works if the file is the main one, but not sure why it works if this module is imported somewhere else.
Now, what I'd like is to instead of being able to use all possible loader classes, to be able to define a subset of all available ones. Basically to have a list/dict to toggle the availability. The use cases are for example,
I'm working on a new loader, but don't want it to be used
I'd like to provide a list of the available loaders.
What I've tried, based on the previously linked answer, is to define a dict with keys as a more user friendly string and values the name of the class that acts as loader.
loaders = {'sqlite': sqlite_loader, 'mysql': mysql_loader}
class loader:
#staticmethod
def get_loader(name):
return loaders[name]()
def available_loaders(self):
return [k for k in available_loaders.keys()]
class sqlite_loader(loader): pass
class mysql_loader(loader): pass
print(type(loader.get_loader('sqlite')))
print(type(loader.get_loader('mysql')))
This code does not work with the error that sqlite_loader is not defined. This I understand, but I'm not being able to find what to add to the loaders dictionary to make it able to find the loader classes.
loaders must be defined after the classes it refers to are defined. Just move the *_loader definitions to the top.
Related
Firstly, thank you for taking the time to read and input. It is greatly appreciated.
Question: What kind of approach can we take to keep the same public API of a class currently using multiple mixins but refactor it internally to be composed of objects that do the same work as the mixin. Autocomplete is a must (so runtime dynamics are kind of out such as hacking things on via __getattr__ or similar - I know this depends on the runtime environment i.e ipython vs pycharm etc, for the sake of this question, assume pycharm which cannot leverage __dir__ I think fully.
Accompanying Information:
I am writing a little assertion library in python and I have a core class which is instantiated with a value and subsequently inherits various assertion capabilities against that value via a growing number of mixin classes:
class Asserto(StringMixin, RegexMixin):
def __init__(self, value: typing.Any, type_of: str = AssertTypes.HARD, description: typing.Optional[str] = None):
self.value = value
self.type_of = type_of
self.description = description
These mixin classes offer various assertion methods for particular types, here is a quick example of one:
from __future__ import annotations
class StringMixin:
def ends_with(self, suffix: str) -> StringMixin:
if not self.value.endswith(suffix):
self.error(f"{self.value} did not end with {suffix}")
def starts_with(self, prefix: str) -> StringMixin:
if not self.value.startswith(prefix):
self.error(f"{self.value} did not end with {prefix}")
I would like to refactor the Asserto class to compose itself of various implementations of some sort of Assertable interface rather than clobber together a god class here with Mixins, I'm likely to have 10+ Mixins by the time I am finished.
Is there a way to achieve the same public facing API as this mixins setup so that client code has access to everything through the Asserto(value).check_something(...) but using composition internally?
I could define every single method in the Asserto class that just delegate to the appropriate concrete obj internally but then I am just making a massive god class anyway and the composition feels like a pointless endeavour in that instance?
for example in client code, I'd like all the current mixins methods to be available on an Asserto instance with autocomplete.
def test_something():
Asserto("foo").ends_with("oo")
Thank you for your time. Perhaps using the mixin approach is the correct way here, but it feels kind of clunky.
I've built a class to ask a user a question, based on a type.
class Question:
def __init__(self, subject):
self.subject = subject
self.question = f"Enter the {subject} to be created. You may end this by typing 'DONE':\n"
self.still_needed = True
def ask_question(self):
ans_list = []
running = True
while running:
var = input(f"Enter {self.subject}?\n")
if var.lower() == 'done':
running = False
else:
ans_list.append(var)
return ans_list
The idea is to have a question model, to create lists of items.
This seems to work well with the following code in main.
roles = Question(subject="role").ask_question()
This creates a list from the Queue Class and uses it's method ask question to generate the list. As far as I can tell the object is then destroyed, as it's not saved to a variable.
My question, being new to Python and OOP is, does this seem like a solid and non-confusing way, or should I refractor? If so, what does the community suggest?
MY OPINION
I guess it depends on you. For one, one of the main purposes of using a class is to create an instance with it later on. Classes are objects ,or "categories" as I like to call them, that you use when there are distinctive types of instances in your project.
Given your code snippet, I can't really suggest anything, I don't know the usage of self.question and self.still_needed. However, if I were to base my opinion on just this part: roles = Question(subject="role").ask_question(), then I'd definitely go with using a function instead. As you've said,
As far as I can tell the object is then destroyed, as it's not saved
to a variable.
ALTERNATIVE SOLUTION
Use decorators → the one with # symbol
In this case, #staticmethod is the way to go!
What are staticmethods? The staticmethod decorator is a way to create a function in a class. So instead of it becoming a method, it can be treated as a function (without self parameter). This also means that a static method bounds to the class rather than its object. Consequently, static methods do not depend on objects (hence, you don't need to create an object for you to use it). Example:
class SomeMathStuff():
#staticmethod
def AddSomeNumbers(iterable):
return sum(iterable)
result = SomeMathStuff.AddSomeNumbers([1, 2, 3])
# result = 6
As you can see, I did not need to create an object, instead I just needed to call its class to use it. Word of warning, most Python programmers argue that this is the un-Pythonic way, but I wouldn't worry too much about it. Hell, even I use these methods sometimes. In my defense, this is a good and efficient way to organize your project. With this, you can apply class methods globally and you can "categorize" them in certain classes you find suitable.
Anyway, this is all I have! I apologize if I misinformed you in any way.
ADDITIONAL INFROMATION ... in case I wasn't the best teacher
https://www.programiz.com/python-programming/methods/built-in/staticmethod
Difference between staticmethod and classmethod
https://softwareengineering.stackexchange.com/questions/171296/staticmethod-vs-module-level-function
I am currently developing a piece of software where the I have class instamces that are generated from dictionaries. The way these dictionariea file are structured is as follows:
layer_dict = {
"layer_type": "Conv2D",
"name": "conv1",
"kernel_size": 3,
...
}
Then, the following code is ran
def create_layer(layer_dict):
LayerType = getattr(layers, layer_dict['layer_type']
del layer_dict['layer_type']
return LayerType(**layer_dict)
Now, I want to support the creation of new layer types (by subclassing the BaseLayer class). I've thought of a few ways to do this and thought I'd ask which way is best and why as I don't have much experience developing software (finishing an MSc in comp bio).
Method 1: Metaclasses
The first method I thought of was to have a metaclass that registers every subclass of BaseLayer in a dict and do a simple lookup of this dict instead of using getattr.
class MetaLayer(type)
layers = {}
def __init__(cls, name, bases, dct):
if name in MetaLayer.layers:
raise ValueError('Cannot have more than one layer with the same name')
MetaLayer.layers[name] = cls
Benefit: The metaclass can make sure that no two classes have the same name. The user doesn't need to think about anything but subclassing when creating new layers.
Downside: Metaclasses are difficult to understand and often frowned upon
Method 2: Traversing the __subclasses__ tree
The second method I thought of was to use the __subclassess__ function of BaseLayer to get a list of all subclasses, then create a dict with Layer.__name__ as keys and Layer as values. See example code below:
def get_subclasses(cls):
"""Returns all classes that inherit from `cls`
"""
subclasses = {
sub.__name__: sub for sub in cls.__subclasses__()
}
subsubclasses = (
get_subclasses(sub) for sub in subclasses.values()
)
subsubclasses = {
name: sub for subs in subsubclasses for name, sub in subs.items()
}
return {**subclasses, ** subsubclasses}
Benefit: Easy to explain how this works.
Downside: We might end up with two layers having the same name.
Method 3: Using a class decorator
The final method is my favourite as it doesn't hide any implementation details in a metaclass, and still manages to prevent multiple classes with the same name.
Here the layers module has a global variable named layers and a decorator named register_layer, which simply adds the decorated classes to the layers dict. See code below.
layers = {}
def register_layer(cls):
if cls.__name__ in layers:
raise ValueError('Cannot have two layers with the same name')
layers[cls.__name__] = cls
return cls
Benefit: No metaclasses and no way of having two layers with the same name.
Downside: Requires a global variable, which is often frowned upon.
So, my question is, which method is preferable? And more importantly, why?
Actually - that is the kind of things metaclases are designed for. As you can see from the options you stated above, it is the simpler and more straightforward design.
They are sometimes "frowned upon" because of two things: (1) people don't understand then and don't care for understanding; (2) people misuse then when they are actually not needed; (3) they are hard to combine - so if any of your classes is to be used with a mixn that have a different metaclass (say abc.ABC), you have also to produce a combining metaclass.
Method 4: __init_subclass__
Now, that said, from Python 3.6, there is a new feature that can cover your usecase without the need for metaclasses: the class __init_subclass__ method:
it is called as a classmethod on the base class when subclasses of it are created.
All you need is to write a proper __init_subclass__ method on your BaseLayer class and have all the benefits you'd have from the implementation in the metaclasses and none of the downsides
Like you, I like the class decorator approach as it is more readable.
You can avoid using a global variable by making the class decorator itself a class, and making layers a class variable instead. You can also avoid possible name collision by joining the target class' name with its module name:
class register_layer:
layers = {}
def __new__(cls, target):
cls.layers['.'.join((target.__module__, target.__name__))] = target
return target
I've come across the following convention, the init.pp is as minimal as possible and looks like this for the example of a java8 module in modules/java8/init.pp
import "*"
class java8 {
include java8::java8
}
Then a modules/java8/java8.pp defines the actual rules/implementations:
class java8::java8 {
# ...
}
Is this a convention, is it an old convention and deprecated? What would or is the rational behind this?
I'm not familiar with that style as any widely-used convention, and I see only limited value to it. Specifically, it appears to serve as a compromise between code organization interests and usage interests: it allows that every class of consequence will be defined in a manifest file named after it (including the delegate main class, java8::java8, in modules/java8/manifests/java8.pp), while providing a main class for the module with a one-segment qualified name (java8), so that users can simply
include 'java8'
I think it's fairly common nowadays to keep the main class small by making it delegate the details to other, private, classes inside the module, but I don't see much value in delegating to exactly one other class for (apparently) naming purposes alone. I also think it's potentially confusing to have different classes with the same unqualified name (java8) in the same module.
How do I supply a configured value to a #view_config-decorated function or class?
E.g.
#view_config(route_name='example', renderer=some_config['template.name'])
class MyClass(BaseView):
...
Or
#view_defaults(route_name='example', renderer=some_config['template.name2'])
class MyClass2(BaseView):
...
Or
#view_config(route_name='example', renderer=some_config['template.name3'])
def method3(request):
...
It's very hard to know where to start, as I'm trying to edit a pyramid plugin, which pulls together its config in an includeme function, so it doesn't have anything obvious that I can include, and it's hard to know what's available to the #view_config decorator.
You can add views using declarative configuration (what you are doing now using #view_config or alternatively using imperative configuration by calling config.add_view() method.
In this case, as you need to access the Pyramid registry and settings file, it is easier to do adding the views imperatively.
In your __init__.py you can do:
settings = config.registry.settings
# You need to call config.add_route("foobar") to map view to URL also
config.add_view('views.MyClass', route_name="foobar", renderer=settings['template.name3'])
Then in your views.py:
class MyClass(BaseView):
pass
#view_config() and add_view() arguments are equal.
I thin kyou can also mix view_config and add_view() arguments for the same view, but I am not sure aobut this. Hope this helps.