Search code examples
pythonclasspropertiesstatic-methodsclass-method

Enforce that static and class methods can only be called through instance and not through class


Professor gave us the following code:

class Dolar:

    @staticmethod
    def dolar():
        return 4680
    
    def __init__(self,pesos):
        self.pesos = pesos

    def convertir(self):
        return self.pesos * Dolar.dolar()
    
if __name__ == '__main__':

    print(Dolar.dolar())
    valor_actual = Dolar(5000)
    print(valor_actual.dolar())
    print(f'{valor_actual.convertir():,}')

Which prints the value for the method "dolar" through both instance and class. Now he wants us to prevent calling said method through the class so that it can only be done through instance.

We recently learned about @property in python so it may be related.

Edit: I am not completely sure what the proffesor wants to happen when calling Dolar.dolar vs valor_actual.dolar because he was purposefully ambiguous but I'm assuming he meant calling Dolar.dolar should give out an error while valor_actual.dolar should give the actual value.


Solution

  • You can implement your own static method descriptor by overriding the __get__ method with a check that the applicable object is None, in which case the method is called via the class:

    class StaticMethod:
        def __init__(self, f):
            self.f = f
    
        def __get__(self, obj, objtype=None):
            if not obj:
                raise NotImplementedError('Must be called via an instance.')
            return self.f
    
        def __call__(self, *args, **kwargs):
            return self.f(*args, **kwargs)
    
    class Dolar:
        @StaticMethod
        def dolar():
            return 4680
    

    Demo: https://replit.com/@blhsing/VengefulThoughtfulSyndrome