问题标签 [decorator]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
590 浏览

python - 如何实现具有非本地平等的装饰器?

问候,目前我正在重构我的一个程序,我发现了一个有趣的问题。

我在自动机中有过渡。转换总是有一个开始状态和一个结束状态。一些转换有一个标签,它对遍历时必须执行的某个动作进行编码。没有标签就意味着没有行动。一些转换有一个条件,必须满足才能遍历这个条件,如果没有条件,则转换基本上是 NFA 中的 epsilon-transition 并且将在不消耗输入符号的情况下进行遍历。

我需要以下操作:

  • 检查转换是否有标签
  • 得到这个标签
  • 为过渡添加标签
  • 检查转换是否有条件
  • 得到这个条件
  • 检查平等

从前五点来看,这听起来像是一个清晰的装饰器,有一个基本的过渡和两个装饰器:Labeled 和 Condition。但是,这种方法有一个问题:如果两个转换的开始状态和结束状态相同,则两个转换被认为是相等的,两个转换处的标签相等(或不存在)并且两个条件相同(或不存在) . 使用装饰器,我可能有两个转换 Labeled("foo", Conditional("bar", Transition("baz", "qux"))) 和 Conditional("bar", Labeled("foo", Transition("baz) ", "qux"))) 需要非局部相等,也就是说,装饰器需要收集所有数据,并且转换必须在集合基础上比较这些收集的数据:

这是一种干净的方法吗?我错过了什么吗?

我很困惑,因为我可以使用协作多重继承来解决这个问题——使用更长的类名:

LabledConditionalTransition 类的行为与预期完全一样——并且没有代码很吸引人,我不认为 MI 在这种大小下会令人困惑。

当然,第三种选择是将所有东西都锤入一个带有一堆 in has_label/has_transition 的转换类中。

所以......我很困惑。我错过了什么吗?哪个实现看起来更好?你如何处理类似的情况,即看起来像装饰器的对象可以处理它们,但是,这样的非本地方法出现了?

编辑:添加了 ConditionalTransition 类。基本上,这有点像装饰器,减去创建装饰器的顺序,过渡检查开始和结束是否正确,LabeledTransition 类检查标签是否正确,ConditionalTransition 检查条件是否正确。

0 投票
8 回答
18958 浏览

python - 保留装饰函数的签名

假设我写了一个装饰器,它做了一些非常通用的事情。例如,它可能会将所有参数转换为特定类型、执行日志记录、实现记忆等。

这是一个例子:

到目前为止一切都很好。然而,有一个问题。修饰函数不保留原始函数的文档:

幸运的是,有一个解决方法:

这一次,函数名称和文档是正确的:

但是还有一个问题:函数签名是错误的。信息“*args, **kwargs”几乎没用。

该怎么办?我可以想到两个简单但有缺陷的解决方法:

1 -- 在文档字符串中包含正确的签名:

由于重复,这很糟糕。签名仍不会在自动生成的文档中正确显示。更新函数并忘记更改文档字符串或打错字很容易。[是的,我知道文档字符串已经复制了函数体。请忽略这个;funny_function 只是一个随机的例子。]

2 -- 不使用装饰器,或为每个特定签名使用专用装饰器:

这适用于具有相同签名的一组函数,但通常没用。正如我一开始所说,我希望能够完全通用地使用装饰器。

我正在寻找一种完全通用且自动的解决方案。

所以问题是:有没有办法在创建装饰函数签名后对其进行编辑?

否则,我可以编写一个装饰器来提取函数签名并在构造装饰函数时使用该信息而不是“*kwargs,**kwargs”吗?我如何提取这些信息?我应该如何构造装饰函数——使用 exec?

还有其他方法吗?

0 投票
4 回答
16623 浏览

python - 如何编写恢复 cwd 的装饰器?

如何编写一个装饰器,将当前工作目录恢复到调用装饰函数之前的状态?换句话说,如果我在执行 an 的函数上使用装饰器,os.chdir()则调用函数后 cwd 将不会更改。

0 投票
8 回答
2008 浏览

design-patterns - 灵活的装饰器模式?

我正在寻找一种模式来模拟我正在考虑在个人项目中做的事情,并且我想知道修饰器模式的修改版本是否可以工作。

基本上我正在考虑创建一个游戏,其中角色属性通过他们装备的物品进行修改。装饰器堆叠其修改的方式非常适合这一点,但是我从未见过允许您删除中间装饰器的装饰器,当物品未装备时会发生这种情况。

有没有人以这种方式使用装饰器模式的经验?还是我在叫错树?

澄清

解释“中间装饰器”,例如,如果我的基类是用牛奶装饰的咖啡,用糖装饰的牛奶(使用 Head first 设计模式中的示例)牛奶将是中间装饰器,因为它装饰了基础咖啡,并被装饰由糖。

还有更多的澄清:)

这个想法是物品会改变统计数据,我同意我将装饰器硬塞进这个。我会查看状态袋。本质上,我想要一个统计数据点,并在装备/不装备物品时让它们上升/下降。

我可以将修改器应用于装备时的角色统计数据,并在取消装备时将它们回滚。或者每当要求统计数据时,遍历所有项目并计算统计数据。

我只是在这里寻找反馈,我知道我可能正在使用电锯,剪刀更合适......

0 投票
11 回答
8264 浏览

java - 改进的集合迭代器

就个人而言,我发现 java.util.Iterator 提供的功能范围相当可悲。至少,我希望有以下方法:

  • peek() 返回下一个元素而不向前移动迭代器
  • previous() 返回前一个元素

尽管还有很多其他的可能性,例如 first() 和 last()。

有谁知道这样的第 3 方迭代器是否存在?它可能需要实现为 java.util.Iterator 的装饰器,以便它可以与现有的 java 集合一起使用。理想情况下,它应该是“泛型意识”。

在此先感谢,唐

0 投票
2 回答
1781 浏览

python - 在 Django 中,如何使用 Django 的 update_object 通用视图来编辑继承模型的形式?

在 Django 中,给出了应用程序动物的摘录,如下所示:

带有以下内容的动物/模型.py

还有一个动物/urls.py

如何使用通用视图来编辑 Dog 和/或 Cat 使用相同的表单?

即传递给animals/animal_form.html的表单对象将是Animal,因此不会包含派生类Dog 和Cat 的任何细节。我怎么能让 Django 自动将子类的表单传递给animal/animals_form.html

顺便说一句,我使用Djangosnippets #1031进行 ContentType 管理,因此 Animal 将有一个名为as_leaf_class的方法,该方法返回派生类。

显然,可以为每个派生类创建表单,但这是很多不必要的重复(因为模板都是通用的——本质上是 {{ form.as_p }})。

顺便说一句,最好假设 Animal 可能是具有相同问题的几个不相关的基类之一,因此理想的解决方案将是通用的。

预先感谢您的帮助。

0 投票
4 回答
10836 浏览

python - 为什么使用 Python 装饰器而不是闭包?

我仍然对 Python 中的装饰器一无所知。

我已经开始使用很多闭包来做一些事情,比如在我的编码中自定义函数和类。

例如。

据我所知,装饰器只是做类似事情的不同语法。

代替

我会写:

这就是装饰者的全部吗?还是我错过了根本的区别?

0 投票
17 回答
206431 浏览

python - 如何获取方法参数名称?

给定 Python 函数:

如何提取参数的数量和名称。即,鉴于我有一个参考func,我想要func.[something]返回("arg1", "arg2")

使用场景是我有一个装饰器,并且我希望按照它们作为键出现在实际函数中的相同顺序使用方法参数。即,"a,b"当我打电话时,装饰器会如何打印a_method("a", "b")

0 投票
3 回答
4279 浏览

java - 为什么我们需要装饰器设计模式中的装饰器?

假设我有一个名为 的类A,并且我想使用装饰器设计模式。如果我错了,请纠正我,但要让它工作,我们需要创建一个装饰器类,比如说ADecorator,它将保存对A实例的引用,并且所有其他装饰器将扩展它以添加功能。

我不明白为什么我们必须创建一个装饰器类,而不是使用一个A实例?

0 投票
3 回答
9387 浏览

python - 调用前的 Python 装饰函数

我有一个由其他人编写的相当复杂的装饰器。我想要做的是根据决定一次调用函数的修饰版本,或者再次调用原始函数(未修饰)。这可能吗?