gpt4 book ai didi

python - 我怎样才能让这些计数器装饰器为我的类方法工作

转载 作者:行者123 更新时间:2023-11-30 22:09:15 26 4
gpt4 key购买 nike

我对装饰器很陌生,并且相信我在很大程度上理解他们的目的/他们的一般要点。不幸的是,我对这个装饰器及其在类中的使用有一些问题。我正在尝试填充字典 _profile_dict = {}使用 profile + str(<counter value>) 创建的新 key 。我不想实例化该类并将其设置为我的 if __name__ == '__main' 中的变量语句,所以我尝试使用 create_profiles 执行该类功能。这是我的代码,

_profile_dict = {}


class Profile:
def __init__(self):
self.first_name = input('first name: ')
self.last_name = input('last name: ')
self.email = input('email: ')
self.address1 = input('primary address: ')
self.address2 = input('secondary address: ')
self.city = input('city: ')
self.country = input('country: ')
self.province = input('province: ')
self.zip = input('zip: ')
self.phone = input('phone number:')
self.cc_name = input('Name on credit card: ')
self.cc_num = input('Credit card number: ')
self.exp_month = input('card expiration month: ')
self.exp_year = input('card expiration year: ')
self.cvv = input('cvv: ')

self.json_obj = {"utf8": "✓",
"_method": "",
"authenticity_token": "",
"previous_step": "",
"checkout[email]": self.email,
"checkout[buyer_accepts_marketing]": 1,
"checkout[shipping_address][first_name]": self.first_name,
"checkout[shipping_address][last_name]": self.last_name,
"checkout[shipping_address][address1]": self.address1,
"checkout[shipping_address][address2]": self.address2,
"checkout[shipping_address][city]": self.city,
"checkout[shipping_address][country]": self.country,
"checkout[shipping_address][province]": self.province,
"checkout[shipping_address][zip]": self.zip,
"checkout[shipping_address][phone]": self.phone,
"step": ""}

def counter(self, func):
def wrapper():
wrapper.counter += 1
return func(wrapper.counter)

wrapper.counter = 0
return wrapper

@counter
def _populate_profile_dict(self, count):
profile = 'profile'
_profile_dict[profile + str(count)] = self.json_obj
print(_profile_dict)


def create_profiles():
Profile()._populate_profile_dict()

if __name__ == "__main__":
create_profiles()

目前,我收到以下错误,

Traceback (most recent call last):
File "C:/Users/Carsten/Profile_Gen/src/config.py", line 6, in <module>
class Profile:
File "C:/Users/Carsten/Profile_gen/src/config.py", line 49, in Profile
@counter
TypeError: counter() missing 1 required positional argument: 'func'

虽然从我刚刚读到的内容来看,Python decorators in classes ,我假设这是不可能的。是否有可能通过 @classmethod 实现我想要实现的目标?

仅将最后 3 个函数/方法更改为此,仍然导致没有输出:

@classmethod
def counter(cls, func):
def wrapper():
wrapper.counter += 1
return func(wrapper.counter)

wrapper.counter = 0
return wrapper

def _populate_profile_dict(self, count):
profile = 'profile'
_profile_dict[profile + str(count)] = self.json_obj
print(_profile_dict)

#def create_profiles():
# Profile()._populate_profile_dict()


if __name__ == "__main__":
Profile()._populate_profile_dict =
Profile.counter(Profile._populate_profile_dict)

如有任何帮助,我们将不胜感激。感谢您的时间。我觉得装饰器以及我议程上的其他一些事情肯定会帮助我进入 python 的中间阶段。

最佳答案

现在让我忽略你的第二次尝试,因为第一次尝试更接近工作:

def counter(self, func):
def wrapper():
wrapper.counter += 1
return func(wrapper.counter)

wrapper.counter = 0
return wrapper

@counter
def _populate_profile_dict(self, count):
# ...

这不起作用的原因是装饰器语法试图执行此操作:

_populate_profile_dict = counter(_populate_profile_dict)

...但是 counter 被定义为接受两个参数,而不是一个,self 和一个函数。这里显然没有self。事实上,连类本身都不存在,更不用说任何方法了。您只需使用函数来调用它,因此这就是它所需要的。

如果您只是删除该 self 参数,装饰器部分将正常工作:

def counter(func):
def wrapper():
wrapper.counter += 1
return func(wrapper.counter)

wrapper.counter = 0
return wrapper

现在,counter 不再作为类实例上的方法有用,但这没关系,因为您永远不会打算以这种方式使用它。

同时,当类仍在定义时,它作为普通函数非常有用。这正是您想要的使用方式。

counter 最终看起来像 Profile 实例的公共(public)方法,这可能会有点令人困惑,尽管它实际上并不能以这种方式调用,这非常令人困惑。但是您可以通过将其重命名为 _counter 或在类定义的最后执行 del counter 来解决该问题。

<小时/>

无论如何,装饰器部分可以工作,但是还有第二个问题:

def wrapper():

这定义了一个没有参数的函数。但是您正在尝试创建可以作为普通实例方法调用的东西,因此它将传递一个 self 参数。您需要接受该 self 参数,并且还需要将其传递给包装的函数。所以:

def counter(func):
def wrapper(self):
wrapper.counter += 1
return func(self, wrapper.counter)
# etc.
<小时/>

现在,一切都按照(我认为)您的预期进行。

<小时/>

当我们这样做时,这段代码有点奇怪:

def create_profiles():
Profile()._populate_profile_dict()

这将创建一个 Profile 实例,调用其私有(private)方法,然后丢弃该实例。我不确定你为什么要这样做。当然,它会向私有(private)全局 _profile_dict 添加一个 profile1 条目,但是这会给您带来什么呢?

<小时/>

现在进行第二次尝试:

@classmethod
def counter(cls, func):
def wrapper():
wrapper.counter += 1
return func(wrapper.counter)

wrapper.counter = 0
return wrapper

现在您已成功创建一个公共(public)classmethod,您尝试将其显式调用为classmethod,这是完美的:

Profile()._populate_profile_dict = 
Profile.counter(Profile._populate_profile_dict)

但它还有多个其他问题:

  • 尝试将作业拆分为两行,就像这样,会出现SyntaxError
  • Profile.counter(Profile._populate_profile_dict) 返回一个新函数,您不会调用该函数,因此它只是将函数本身分配为值。
  • 当您确实调用它时,它期望有两个参数,一个self和一个count,但您只传递了计数。在这里,尚不清楚您想从哪里获取 self 。也许您想在 Profile 的实例上调用它,这样您就可以获得一个 self 并可以传递它?
  • 您正在将值分配给刚刚创建且即将丢弃的 Profile 实例的实例属性,这没有任何可见效果。
  • 该实例属性与您要调用的方法具有相同的名称 - 这是合法的,并且不会在此处引起任何特定问题,但它非常令人困惑。

我能看到的最合理的事情是让 counter 返回可调用的方法作为方法,如上所述:

@classmethod
def counter(cls, func):
def wrapper(self):
wrapper.counter += 1
return func(self, wrapper.counter)

wrapper.counter = 0
return wrapper

...然后使用结果进行 Monkeypatch Profile ,然后在 Profile 实例上调用该方法,如下所示:

if __name__ == "__main__":
Profile._populate_profile_dict = Profile.counter(Profile._populate_profile_dict)
Profile()._populate_profile_dict()

现在它可以工作了,但我不确定这是否是你想要的。

关于python - 我怎样才能让这些计数器装饰器为我的类方法工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51976665/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com