Is it possible for the main module to tailor the definition of a class in an imported module?

The question arises because I’m trying to break a larger module with multiple classes into several smaller single-class modules.

In the large module, I used a variable with module scope to determine whether certain diagnostic functions would be defined. E.g.:

gTest = True  # Generate diagnostic functions

class oTest:
  if gTest:
    def fTest( s, aWord):
      print( aWord)

But now, after “refactoring”, class oTest is in a different module, and in that module, gTest is undefined.

I can pass gTest to the oTest __init__(), and include the last three lines, above, in __init__(), but this would make the __init__() unwieldy and would put the fTest() definition far from its natural position.

However, if I put the last three lines outside of __init__(), then the gTest value will be the initial class variable, not the instance variable set by __init__():

Main module:

  gTest = True
  from mTest import oTest
  x = oTest( gTest)

Module mTest:

class oTest:
  gTest = False

  def __init__( s, aTest):
    s.gTest = aTest   # Sets instance varlable, not class variable
  ...  
  if gTest:              # class variable (False), not instance variable (True)     
    def fTest( aWord):
      print( aWord)

(1) Am I using the right terminology and understanding the problem correctly?
(2) Is this a problem that a metaclass or “factory class” can solve?

This looks like an overcomplicated design. Could you please explain:

  • What are the cases that gTest = True and gTest = False?
  • Why do not you simply define the methods like fTest() always?

To retain your original functionality simply create a module for the gTest variable and import it where needed.

Here gTest is called class attribute. It is a variable in the name scope of the class.

Also I would strongly recommend following the Python style:

  • CamelCase - classes
  • snake_case - variables, functions, methods
  • UPPER_CASE - constants

Thank you for responding.

What are the cases …?

I use gTest = True when debugging and gTest = False when I no longer want the diagnostic code.

… define fTest() always?

Because I don’t want the live version of the program cluttered with unused code.

I could go back to the original design, where everything is in a single module, but I am hoping to find a more elegant approach, one that gives me a chance to explore factory and meta classes, perhaps. I’m here to learn.

the Python style

I like Python, in part because I value the freedom to code in a way that makes sense to me. A style is a fashion, and fashions evolve in response to input from non-conformists.

Python was designed as an interpreted language and in fact in most cases it is being executed as an interpreted language. It is just a detail that there is an automatic compilation to bytecode. The variable gTest is a normal variable and setting it to False does not change much.

It is normal that Python program contains a diagnostic code which normally display state and important events using the logging module. I have never needed many or large functions/methods just for that.

  • If you need to perform real tests (not run-time diagnostics) of your code, use pytest.
  • You can also try to use a debugger.
  • If large parts of the diagnostic code are the output formatting you can probably create a separate module / class just for the diagnostic output formatting. Then you can import the module conditionally. This would save a little bit more resources.

As I already wrote, to retain your desing, you can create a separate module for the variable gTest and import it where needed. You can also set the variable from the command line parameters or a config file.

:open_mouth: Are we talking about coding conventions / programming style? Programming normally involves a lot of cooperation in the form of getting information from the other people, analyzing code of other people, other people analyzing your code… For this the style is very important to avoid making all the effort much much bigger. One of the main ideas of Python is the readability of the code. The official style was designed to support the readability.

Of course for experiments, you can do anything but it does not seem that this is an experiment.

Problem solved!

I found that I can use a function in mTest to define the oTest class. I pass the gTest control variable to the function, and the function then selects what parts of the class to include. It’s a clean solution, and implementing it turned out to be much easier than I expected. This is the first time I’ve used a class factory – but it won’t be the last! Python is amazing.

Thank you again for your response. The program is indeed an experiment – a learning experiment. I am not working for a large corporation; I am simply developing a game for use by myself and my friends, and since I am the only programmer on this project, I am free to use a naming convention that makes sense to me. Moreover, when I read the Python tutorial, I do not find strict conformance to the recommended naming convention; instead, I find names like imagpart, counter, do_local. cls, etc…

1 Like

I am glad that you have found a solution.

I suggested a parametrized class decorator. Later I realized it does not resolve your problem because you will need to have the deciding value in the same scope as the class definition... Anyway the original reply is hidden here.

Python has ways how to make your solution better. Instead of the special mTest() function generating just a single class create a more generic re-usable class decorator[1]. Then you can write something like:

@mTest(gTest=True)
class oTest:
    ...

Useful resources:

I noticed that in my previous message I did not conclude my thought to an explicit statement. I wanted to say that you will have the methods anyway simply because it does not work like in compiled languages - e.g. like #ifdef DEBUG in the C language.


  1. like @dataclasses.dataclass in the standard library ↩︎