【问题标题】:Python decorator crashing even though its code is solid, can't understand whyPython 装饰器崩溃,即使它的代码是可靠的,不明白为什么
【发布时间】:2021-12-30 13:20:08
【问题描述】:

所以我编写了一个名为“anonimize”的函数,它使用正则表达式获取一个字符串并返回该字符串,其中一些细节被涂黑。 该函数本身可以正常工作,但我试图将它变成一个装饰器,结果却出现了很多次崩溃。 我正在学习装饰器,并且真的很想了解我做错了什么。 在这个不成功的版本中,我得到了“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: johndoe@fakemail.com\nAccount number: 911911911.")

【问题讨论】:

  • 我更正了缩进

标签: python class crash decorator python-decorators


【解决方案1】:

您需要将anonimize 移出课堂。为什么?

传递给标准方法的第一个参数始终是拥有对象本身(self 参数是标准语法,但您可以调用任何名称)。

您不能将其用作静态方法,因为在定义代码时会运行装饰器。您将无法引用拥有的对象,因为它还没有被实例化。

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 .)
   '''

    ...

【讨论】:

  • 关于@staticmethod 的有趣注释,我没想到。我会编辑我的答案
  • 谢谢 :) 我也这么认为,这也是老师希望我们做的。无论如何,我把装饰器从课堂上拿了出来,现在我得到了:“TypeError: anonimize..inner() 接受 1 个位置参数,但给出了 2 个”
  • @swapman this thread 应该可以帮助您解决 TypeError
【解决方案2】:

anonimize 不应该是BankApplication 的实例方法,它甚至不接受self。在类之外定义它。

编辑:我也建议@staticmethod,但它也不起作用,请参阅@James 的回答。

【讨论】:

  • arg 在定义的地方应该是 *arg,在使用的地方应该是 arg[1]
  • @luk2302,是的,理想情况下,装饰者应该def inner(*args, **kwargs),但我不确定在这种情况下我是否同意你的看法。看起来装饰器是专门为这些单参数方法设计的,而不是一般用途。 arg[1] 在一般情况下无论如何都不起作用,因为它假定字符串参数始终排在第一位。如果我是 OP,我会简单地将字符串转换函数应用于这些方法内部的参数,而不是装饰它们。还是一行,但更简单。
【解决方案3】:

好的,这是我发布的版本有误

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

这是本应如此

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

【讨论】:

  • 我问是什么原因导致我的程序崩溃。答案是我在类中定义方法时没有使用“self”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-15
  • 2020-01-04
  • 2019-07-14
  • 2019-03-06
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
相关资源
最近更新 更多