是否有任何设计模式用于实施抽象类儿童类方法的装饰?
这种情况使我有一个抽象课程和一些儿童课程实施。
class Parent(metaclass=ABCMeta):
@abstract_method
def first_method(self, *args, **kwargs):
raise NotImplementedError()
@abstract_method
def second_method(self, *args, **kwargs):
raise NotImplementedError()
class Child(Parent):
def first_method(self, *args, **kwargs):
print('First method of the child class called!')
def second_method(self, *args, **kwargs):
print('Second method of the child class called!')
我的目标是制作某种装饰器,该装饰师将用于父母班级的任何孩子的方法。我需要这个,因为每种方法在实际做某事之前都进行了某种准备,并且在父母班级的所有孩子的所有方法中,此准备绝对相同。像:
class Child(Parent):
def first_method(self, *args, **kwargs):
print('Preparation!')
print('First method of the child class called!')
def second_method(self, *args, **kwargs):
print('Preparation!')
print('Second method of the child class called!')
第一件事是使用父类方法实现:只需删除“提高notimplementedError()”并放置一些功能,然后在我称之为的子类中,例如super()。 *args,** kwargs)在每种方法的开头。这很好,但是我也想从父方法返回一些数据,当父级方法和儿童方法返回声明中的某些内容时,看起来很奇怪。更不用说我可能想在方法之后做一些后处理工作,因此我需要2个不同的功能:对于执行脚本的开始和之后。
我想到的下一件事是制作元口。 只需在创建课程过程中实现新元类中方法的所有装饰,然后将新生成的数据传递给儿童方法中的数据。
这是最接近我目标的解决方案,但无论如何都感觉不对。因为并不明确地说,某些夸尔格会传递给儿童方法,如果您是该代码的新手,那么您需要进行一些研究以了解其工作原理。我觉得我过度工程左右。
因此,问题是:这些线上是否有任何模式或其他内容来实现此功能? 也许您可以为我的情况提供更好的建议? 预先感谢您!
The case is such that I have an abstract class and a few child classes implementing it.
class Parent(metaclass=ABCMeta):
@abstract_method
def first_method(self, *args, **kwargs):
raise NotImplementedError()
@abstract_method
def second_method(self, *args, **kwargs):
raise NotImplementedError()
class Child(Parent):
def first_method(self, *args, **kwargs):
print('First method of the child class called!')
def second_method(self, *args, **kwargs):
print('Second method of the child class called!')
My goal is to make some kind of decorator, which will be used on methods of any child of the Parent class. I need this because every method make some kind of preparation before actually doing something, and this preparation is absolutely the same in all methods of all childs of the Parent class. Like:
class Child(Parent):
def first_method(self, *args, **kwargs):
print('Preparation!')
print('First method of the child class called!')
def second_method(self, *args, **kwargs):
print('Preparation!')
print('Second method of the child class called!')
The first thing came to my mind is to use Parent class method implementation: just remove "raise NotImplementedError()" and put some functionality, and then in child classes I would call, for example, super().first_method(self, *args, **kwargs) in the beginning of each method. It is good, but I also would want to return some data from the Parent method, and it would look weird when parent method and child method return something different in declaration. Not to mention that I would probably want to do some post-processing work after the method, so then I would need 2 different functions: for the beginning and after the performing the script.
The next thing I came up with is making MetaClass.
Just implement all the decoration of methods in the new MetaClass during creating a class, and pass the newly generated data which is used in child methods to them in kwargs.
This is the closest solution to my goal, but it feels wrong anyway. Because it is not explicit that some kwargs will be passed to child methods, and if you are new to this code, then you need to do some researches to understand how it works. I feel like I overengineering or so.
So the question: is there any pattern or something along these lines to implement this functionality?
Probably you can advise something better for my case?
Thank you a lot in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因此,现有模式分开:我不知道这是否具有特定的名称,您需要什么,那将是“模式”是使用“插槽”:就是 - 您记录了被称为特殊名称的方法,被称为执行另一种方法的一部分。然后,此另一种方法执行其设置代码,检查是否存在插槽方法(通常可以按名称识别),请使用简单的简单方法调用来调用它们,即使调用特殊方法,它将运行最专业的版本老虎机处于基础类别,您处于一个较大的班级构建层次结构。
此模式的一个简单示例是Python实例化对象的方式:实际上是使用用于函数调用的相同语法调用类的方式(
myClass()
)是该类的类(其Metaclass)__调用__
方法。 (使用usally类型.__调用__
)。在Python的类型中的代码中。第一个调用,返回到
__新的__
。自定义元素可以修改__调用__
以运行以前,之间或之后的任何代码。因此,如果这不是Python,那么您所需要的只是将其规定,并记录不应直接调用这些方法,而是通过“入口点”方法来调用这些方法 - 它可以简单地具有“ EP_”前缀。这些将必须在基础上修复并进行硬编码,并且您需要为每个前缀/Postfix代码的每个方法都需要一种。
这是Python,更容易添加更多魔术以避免代码重复并保持简洁。
一件事是拥有一个特殊的类,该类别在检测儿童类中的方法时,该方法应称为包装器方法的插槽,如上所述,以自动重命名 方法:这样入口点方法可以具有与儿童方法相同的名称 - 更好的是,一个简单的装饰器可以标记为“入口点”的方法,并且继承甚至对他们有用。
基本上,当构建新类时,我们会检查所有方法:如果其中任何一个在调用层次结构中具有通讯部分,该部分标记为入口点,则将进行重命名。
如果将任何入门点方法作为第二个参数(第一个为
self
),则更为实用,这是要调用插入的方法的引用。经过一番摆弄之后:好消息是不需要Custommetaclass-
__ Init_subclass __
基本类中的特殊方法足以启用装饰器。坏消息:由于在最终方法上触发了“超级()”触发的入口点上的重新输入迭代,因此需要在中间类中调用原始方法。我还要注意一些多线程保护措施 - 尽管这不是100%防弹的。
So, existing patterns apart: I won't know if this has an specific name, what you need, that would be a "pattern" is the use of "slots": that is - you document special named methods that will be called as part of the execution of another method. This other method then performs its setup code, checks if the slotted method (usually identifiable by name) exists, call them, with a plain simple method call, which will run the most specialized version of it, even if the special method that calls the slots is in the base class, and you are on a big class-inheritance hierarchy.
One plain example of this pattern is the way Python instantiates objects: what one actually invokes calling the class with the same syntax that is used for function calls (
MyClass()
) is that class's class (its metaclass)__call__
method. (Usallytype.__call__
). In Python's code fortype.__call__
the class'__new__
method is called, then the class'__init__
method is called and finally the value returned by the first call, to__new__
is returned. A custom metaclass can modify__call__
to run whatever code it wants before, between, or after these two calls.So, if this was not Python, all you'd need is to spec down this, and document that these methods should not be called directly, but rather through an "entry point" method - which could simply feature an "ep_" prefix. These would have to be fixed and hardcoded on a baseclass, and you'd need one for each of the methods you want to prefix/postfix code to.
This being Python, it is easier to add some more magic to avoid code repetition and keep things concise.
One possible thing is to have a special class that, when detecting a method in a child class that should be called as a slot of a wrapper method, like above, to automatically rename that method: this way the entry point methods can feature the same name as the child methods - and better yet, a simple decorator can mark the methods that are meant to be "entrypoints", and inheritance would even work for them.
Basically, when building a new class we check all methods: if any of them has a correspondent part in the calling hierarchy which is marked as an entrypoint, the renaming takes place.
It is more practical if any entrypoint method will take as second parameter (the first being
self
), a reference for the slotted method to be called.After some fiddling: the good news is that a custommetaclass is not needed - the
__init_subclass__
special method in a baseclass is enough to enable the decorator.The bad news: due to re-entry iterations in the entry-point triggered by potential calls to "super()" on the final methods, a somewhat intricate heuristic to call the original method in the intermediate classes is needed. I also took care to put some multi-threading protections - although this is not 100% bullet-proof.