1

I have the following class:

import Radar

class Domain(Radar):
    URL = 'https://mxtoolbox.com/DNSLookup.aspx'
    ADDRESS_KEYS = ('mailing_address', 'city_name', 'state_name', 'zip_code',
                    'country_name')
    GENERAL_PARAMS = {'format': 'json'}
    BALANCE_PARAMS = {**Radar.GENERAL_PARAMS, 'account': 'balance'}
    SUCCESSFUL_QUERY = 1
    API_KEY_ERROR_REASON = 'Invalid API Key'
    MASKED_ENTITY_INDICATOR = 'To View Unmasked Data'

    def __init__(self, *args, **kwargs):
        self.entity_title = 'Crawling'
        super().__init__(*args, **kwargs)

The class' methods (only them) access each of these constant static members few times.

What are the advantages/disadvantages of putting these variables in the outer scope (as a file level variables - and not class level static variables)?

Even though I know both approaches would work, I wonder where is the best place put the variables - inside the class or above it.

The other option:

import Radar

URL = 'https://mxtoolbox.com/DNSLookup.aspx'
ADDRESS_KEYS = ('mailing_address', 'city_name', 'state_name', 'zip_code',
                'country_name')
GENERAL_PARAMS = {'format': 'json'}
BALANCE_PARAMS = {**Radar.GENERAL_PARAMS, 'account': 'balance'}
SUCCESSFUL_QUERY = 1
API_KEY_ERROR_REASON = 'Invalid API Key'
MASKED_ENTITY_INDICATOR = 'To View Unmasked Data'

class Domain(Radar):
    def __init__(self, *args, **kwargs):
        self.entity_title = 'Crawling'
        super().__init__(*args, **kwargs)
1

This is a mostly stylistic choice. In the end, it doesn't matter. There are some finer differences depending on how they are used.

  • If the constants are only used within the module, using module-level variables is more convenient. (Compare class variables below).

  • If the constants are used outside of this module, then module-level variables have the advantage that you can import them.

  • Class variables have the advantage that they are bundled in that class. This may provide a more convenient interface because you don't have to pass them around individually. For example, the Enum class does this nicely. But in reverse: why would you be bundling them unless they are used together?

Class variables in Python do have some gotchas.

  • Python doesn't have true constants, so anyone could reassign them. (To create read-only fields in Python, you must use a property, or more generally: the descriptor protocol).
  • These variables can be shadowed by subclasses, or by instance variables.
  • The variables can only be accessed through the class or its instances. E.g. to access the URL variable in a method, you have to say Domain.URL or self.URL. Module-level variables can be accessed directly.

In general, Python doesn't force you to stuff everything into a class. You should use this freedom because most variables or functions don't belong into a class. If in doubt, use free variables/functions instead of fields/methods within a class. You can always change your mind later and refactor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.