Home > Mobile >  Python decorator crashing even though its code is solid, can't understand why
Python decorator crashing even though its code is solid, can't understand why

Time:12-31

So I wrote a function called 'anonimize' that gets a string and returns that string with some details blacked-out, using regex. The function works fine on its own, but I tried to turn it into a decorator and things went south and got so many crashes so many times. I am learning decorators and would really like to understand what I am doing wrong. In this unsuccessful version I got "TypeError: BankApplication.anonimize() missing 1 required positional argument: 'callable'".

import re


class BankApplication:

    def __init__(self, bank_name):
        self.name = bank_name

    '''
      Perform anonimization to the text data:
      1. Remove possible account numbers (more than 5 digits in a row)
      2. Remove possible email addresses
      3. Remove possible First   Last names (two consequtive words 
         starting from upper case, but not divided by .)
   '''

    def anonimize(func):
        def inner(arg):
            ret = func(arg)
            print(
                re.sub("[A-Z][a-z] \s[A-Z][a-z] ", "***", re.sub("\S @\S \.\S ", "***", re.sub("\d{5,}", "***", arg))))
            return ret

        return inner

    @anonimize
    def feedback(self, feedback_text):
        print("Called feedback")

    @anonimize
    def log_info(self, info_to_log):
        print("Called feedback")


bank = BankApplication("Bank")
bank.feedback("Name: John Doe\nE-mail: [email protected]\nAccount number: 911911911.")

CodePudding user response:

You need to move anonimize out of the class. Why?

The first argument that gets passed to a standard method is always the owning object itself (the self argument is the standard syntax, but you can call it anything).

You cannot use it as a static method because decorators are run when the code is defined. You won't be able to reference the owning object because it won't have been instantiated yet.

import re

def anonimize(func):
    def inner(arg):
        ret = func(arg)
        print(
            re.sub("[A-Z][a-z] \s[A-Z][a-z] ", "***", re.sub("\S @\S \.\S ", "***", re.sub("\d{5,}", "***", arg))))
        return ret
    return inner

class BankApplication:

    def __init__(self, bank_name):
        self.name = bank_name

    '''
      Perform anonimization to the text data:
      1. Remove possible account numbers (more than 5 digits in a row)
      2. Remove possible email addresses
      3. Remove possible First   Last names (two consequtive words 
         starting from upper case, but not divided by .)
   '''

    ...

CodePudding user response:

anonimize shouldn't be an instance method of BankApplication, it doesn't even accept self. Define it outside of the class.

EDIT: I've also suggested @staticmethod, but it wouldn't work either, see @James's answer.

CodePudding user response:

Ok, so this was the wrong version I posted:

def anonimize(func):
    def inner(text):
        print(re.sub("[A-Z][a-z] \s[A-Z][a-z] ", "***", re.sub("\S @\S \.\S ", "***", re.sub("\d{5,}", "***", text))))
        return func(text)
    return inner

And this is the way it should have been:

def anonimize(func):
    def inner(self, text):
        text = re.sub("[A-Z][a-z] \s[A-Z][a-z] ", "***", re.sub("\S @\S \.\S ", "***", re.sub("\d{5,}", "***", text)))
        return func(self, text)
    return inner
  • Related