gpt4 book ai didi

python - 向对象动态添加方法无法正常工作(setattr)

转载 作者:行者123 更新时间:2023-12-01 00:12:07 31 4
gpt4 key购买 nike

我正在尝试创建一个 class适应django反对导出。我希望其他程序员始终继承这个class如果需要,他们可以通过覆盖来覆盖任何属性:

get__<attr_name>

方法。

所以我所做的是迭代 django模型字段名,对于每个字段名,我设置 get__<attr_name>方法。问题是所有这些方法都返回相同的 True这是最后一个字段名的输出。

class BaseProductExportAdapter():  
def __init__(self, product: Product):
self.product = product
self.eshop = self.product.source.user_eshop

def _set_methods(self):
product_attr_names = Product.get_fieldnames(exclude=[])
# set all getters so we can use get__<any_field> anytime. It can be overriden anytime.
for attr_name in product_attr_names:
setattr(self, 'get__' + attr_name, lambda: getattr(self.product, attr_name))

当我创建BaseProductExportAdapter时实例并设置 product作为参数并调用 b._set_methods() ,我看到这个:

>>> ...
>>> b._set_methods()
>>> b.get__quantity()
>>> True
>>> b.get__<any_valid_fieldname>()
>>> True

你知道为什么它不能正常工作吗?

最佳答案

一个lambda表达式形成一个闭包,用于访问定义变量的范围内的变量的当前值。所以在你的 lambda表达式,当您询问 attr_name 时您将获得 attr_name当前值在 _set_methods 的范围内功能。

这意味着正如您所定义的 _set_methods方法它总是 attr_name 的最后一个值在你的for环形。考虑一下如果在 for 之后显式设置它会发生什么。循环:

    def _set_methods(self):
product_attr_names = Product.get_fieldnames(exclude=[])
# set all getters so we can use get__<any_field> anytime. It can be overriden anytime.
for attr_name in product_attr_names:
setattr(self, 'get__' + attr_name, lambda: getattr(self.product, attr_name))
attr_name = 'foo'

使用上面的代码,b.get__<anything>()最终将始终运行 getattr(self.product, 'foo') .

有关详细信息,请参阅:

您可以通过替换 lambda 来解决这种情况。带有工厂函数的表达式:

    def _set_methods(self):
def attrgetter(attr):
def _():
return getattr(self.product, attr)

return _

product_attr_names = Product.get_fieldnames(exclude=[])
# set all getters so we can use get__<any_field> anytime. It can be
# overriden anytime.
for attr_name in product_attr_names:
setattr(self, 'get__' + attr_name, attrgetter(attr_name))

关于python - 向对象动态添加方法无法正常工作(setattr),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59572576/

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