6

So I hear that modules are very pythonic and I structure my code with modules a lot and avoid classes.

But now I'm writing a module Formula that has a lot of the same functionality as the module Car. How should I handle that?

  • Duplicate code in both modules?
  • Convert to classes?
  • Refactor code to add a third, parent module Vehicle and import methods and variables that I need?

The third looks good, the only downside that I see is that there are some variables that are specific to a module (e.g. top_speed), but the functions in the parent module Vehicle need to access those specific variables.

Paolo
  • 20,112
  • 21
  • 72
  • 113
duality_
  • 17,738
  • 23
  • 77
  • 95
  • Without seeing some of the code, it is hard to advise (and I suspect that, with some code, this is a better fit for http://codereview.stackexchange.com/). However, it sounds like a class-based solution would fit here; a `Car` *is a* `Vehicle`. You could also import functions to `Formula` from `Car`. – jonrsharpe Jan 29 '14 at 14:54
  • @jonrsharpe, I'm always more than a little skeptical of trying to make inheritance fall out of existing hierarchies, like "Car is a Vehicle". Now that we have a couple decades of it, we can see that the OO-as-an-abstract-design-approach strategy is flawed and unhelpful. Inheritance should be about what you need your code to do, not abstract relationships. – Mike Graham Jan 29 '14 at 15:01
  • @MikeGraham in general, that is fair; I think we would need to see more detail of the OPs implementation to see what is best. I was going by their comment that a Vehicle would seem a sensible parent to Car and Formula. – jonrsharpe Jan 29 '14 at 15:04
  • One useful need for such a case is with Swagger CodeGenerator. The module `swagger_client` being created needs to be replaced everytime as is, without any modifications. However because the autogenerated module is not covering all cases sometimes you want to extend it, for example you want to extend the Configuration class to make the `self.host` dynamic and not static. However if you only extend this class in another module the swagger client module is unaware of your extension and thus you need to extend the ENTIRE module and use it. Makes sense ? – George Pligoropoulos Dec 31 '20 at 13:59

5 Answers5

2

A module is an instance, not a class, so you can't inherit from it any more than you can inherit from 6.

If your stuff has state, you should have classes, not modules.

If you have two modules that need the same stuff, then it either a) one of them should have it and the second should use the first, or b) they should both get it from a third module.

Module names are typically lowercase, since Uppercase/CamelCase names indicate classes.

Mike Graham
  • 73,987
  • 14
  • 101
  • 130
1

Modules can sometimes be used to implement Singletons, but they aren't meant to be a replacement for classes. You can only import the module once, while a class can have multiple instances.

If you need inheritance, use a class.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • 2
    Using modules as singletons is certainly done by some people, but is an anti-pattern. It's more testable and more flexible and more maintainable to just store and instance somewhere -- http://glyph.twistedmatrix.com/2007/07/functional-functions-and-python.html – Mike Graham Jan 29 '14 at 14:56
0
class Base():
    .....

class derived(Base):
    ......

But this is inheriting class...

mdml
  • 22,442
  • 8
  • 58
  • 66
Nabin
  • 11,216
  • 8
  • 63
  • 98
0

I wanted to inherit from a module, and I did it:

import json

class custom_json(): pass

for i in json.__all__:
    setattr(custom_json, i, getattr(json, i))

At least it works.

If you will override some attributes, then use it:

import json

class custom_json():
    def dump():
        pass

for i in json.__all__:
    if not hasattr(custom_json, i):
        setattr(custom_json, i, getattr(json, i))
Ekrem Dinçel
  • 1,053
  • 6
  • 17
-1

Let me give you an example:

Base.py

import os
import sys
config = dict()
config['module_name'] = "some_xyz_thing"
config['description'] = "Implements xyz functionality"

Derived.py

from Base import config
config['module_name'] = "som_more_xyz_functionality"

This way you can use inheritance at module level

Arunmu
  • 6,837
  • 1
  • 24
  • 46
  • @MikeGraham Like ? Care to explain. This is an "example". never mentioned it would work as it is – Arunmu Jan 29 '14 at 15:03
  • 2
    `config` isn't defined in Derived.py. Even if you did `from Base import config` instead, then `config['module_name'] = "som_more_xyz_functionality"` would mutate Base.py's version instead. The more important flaw is trying to do this at all rather than addressing a real problem using best practices. (Also you have a syntax error.) – Mike Graham Jan 29 '14 at 15:06
  • Thats what you call override. If you want to extend the base module, just go on adding to the config dict, you will end up having properties defined in both base and derived. Though , you ha have correctly pointed the error in importing, fixing that – Arunmu Jan 29 '14 at 15:11
  • 2
    It's not overriding. It just changes the dict that they share. – Mike Graham Jan 29 '14 at 15:13
  • Cool..another downvote without valid reason and not even waiting for OP view – Arunmu Jan 29 '14 at 15:42