Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it bad practice to put stuff into new function properties?

Tags:

python

Say I have a class and a function:

class AddressValidator(self):
    def __init__(self):
        pass
    def validate(address):
        # ...

def validate_address(addr):
    validator = AddressValidator()
    return validator.validate(addr)

The function is a shortcut for using the class, if you will. Now, what if this function has to be run thousands of times? If the validator class actually has to do something on instantiation, like connecting to a database, creating it over and over thousands of times is pretty wasteful. I was wondering if I could perhaps do something like this:

def validate_address(addr):
    if not hasattr(validate_address, 'validator'):
        validate_address.validator = AddressValidator()

    validator = validate_address.validator
    return validator.validate(addr)

Now the validator class is only instantiated once and saved "in the function", to put it that way. I've never seen this done though, so I'm guessing it's bad practice. If so, why?

Note: I know I can just cache the validator object in a module global. I'm just curious if this is a viable solution when I want to avoid littering my module.

like image 650
Hubro Avatar asked Dec 19 '25 03:12

Hubro


2 Answers

Despite "everithing is an object", not everithing work as nice as instances of well controlled class. This problem looks like typical case for "functor" or "callable object" as it called in python.

the code will be look something like

class AddressValidator(self):
    def __init__(self):
        pass
    def __call__(self,address):
        # ...

validate_address = AdressValidator()

or you could just define your function as shortcut to bound method

class AddressValidator(self):
    def __init__(self):
        pass
    def validate(self,address):
        # ...

validate_adress = AdressValidator().validate
like image 191
Odomontois Avatar answered Dec 20 '25 17:12

Odomontois


I'd go with a default argument (evaluated once at function definition time and bound to the function):

def validate_address(addr, validator=AddressValidator())
    return validator.validate(addr)

This is perfectly acceptable if instances of AddressValidator are considered immutable (i.e. they don't contain methods that modify their internal state), and it also allows you to later override the choice of validator should you find the need to (e.g. to provide a validator specialized for a particular country).

like image 25
nneonneo Avatar answered Dec 20 '25 18:12

nneonneo