gpt4 book ai didi

python - 有什么措施可以将Python代码称为基于策略的设计?

转载 作者:太空宇宙 更新时间:2023-11-03 11:58:01 25 4
gpt4 key购买 nike

说明
我想知道我展示的代码是否可以被视为python中基于策略的设计示例。另外,我想知道您是否见过python模块使用类似于这个示例的东西,以便我可以从中学习?
I wrote more details and examples about this approach in a post.
最近,我需要一个类似于policy-based design的python模块。
我在这个论坛上找到了一个similar question,但它已经关闭,我无法添加评论。
让我总结一下我对Python中这种方法的期望。
模块类分为策略类和主机类。
策略类通过继承实现对宿主类的行为或接口的修改。
用户通过提供一组策略类从宿主类实例化一个新类。
这是我的玩具示例:

class PrintOutput:
"""Implement print output policy."""
def _output(self, message):
print(message)

class SaveOutput:
"""Implement save output policy."""
def set_filename(self, filename):
self.filename = filename
def _output(self, message):
with open(self.filename, 'w') as file:
file.write(message)

def HelloWorld(Output=PrintOutput):
"""Creates a host class."""
class _(Output):
"""Implements class affected by the policy."""
def run(self):
"""Print message."""
self._output('Hello world!')
return _

PrintHelloWorld = HelloWorld()
hw = PrintHelloWorld()
hw.run() # print "Hello World!"

SaveHelloWorld = HelloWorld(
Output=SaveOutput
)
hw = SaveHelloWorld()
hw.set_filename('output.txt')
hw.run() # save "Hello World!" in output.txt

在这个例子中,我希望所有的类都已经在一个模块中定义了用户只需要使用符合其需求的输出策略来实例化helloworld类。
设计成分
基本的设计要素是
多重继承:存在于C++和Python中。
推迟继承:推迟主机类和策略类之间继承的定义,直到用户实例化主机类
// in C++ using templates
template<typename Policy1, typename Policy2, ...>
class HostClass: public Policy1, public Policy2, ... {
// Implement host class.
};

# in Python with a factory with arguments
def HostClass(Policy1, Policy2=Default2, ...):
class _(Policy1, Policy2, ...):
"""Implements class affected by the policies."""
return _

类实例化
// in C++
typedef HostClass<Policy1Class, Policy2Class, ...> NewClass;

# in Python
NewClass = HostClass(Policy1Class, Policy2Class, ...)

使用MIXIN作为替代品
我刚刚从其中一条评论中了解到,可以使用 Python mixins作为创建新类的替代方法。在这种方法下,模块的代码在基础和混合类之间划分。然后,可以从基类创建新类,并使用MIXIN类实现对基类提供的行为或接口的修改。
在这个 answer之后,我能够用Mixin写我的第一个例子。
class PrintOutput:
"""Implement print output mixin."""
def _output(self, message):
print(message)

class SaveOutput:
"""Implement save output mixin."""
def set_filename(self, filename):
self.filename = filename
def _output(self, message):
with open(self.filename, 'w') as file:
file.write(message)

class HelloWorld:
"""Creates a host class."""
def run(self):
"""Print message."""
self._output('Hello world!')

class PrintHelloWorld(PrintOutput, HelloWorld):
pass

hw = PrintHelloWorld()
hw.run() # print "Hello World!"

class SaveHelloWorld(SaveOutput, HelloWorld):
pass

hw = SaveHelloWorld()
hw.set_filename('output.txt')
hw.run() # save "Hello World!" in output.txt

方法之间的差异
MIXIN与我之前的示例的主要区别是类之间的继承层次结构。无论是MIXIN还是基础类都不能推断哪一个是MIXIN或基于类的角色。这是因为它们都是PrintHelloWorld或SaveHelloWorld等新类的父类。
在我尝试进行基于策略的设计时,宿主类总是可以知道哪些类是其策略,因为它们是其父类。这个特性允许我利用python的方法解析顺序(method resolution order,mro)在主机类和策略类之间创建组合。这些组合是使用实例化的主机类作为策略来实例化另一个主机类的结果,请参见下面的示例。
class InputMessage:
"""Generate the message."""
def run(self):
return 'hello world'

def AddPrefix(Input):
"""Add a prefix."""
class _(Input):
def set_prefix(self, prefix):
self._prefix = prefix
def run(self):
return self._prefix + super().run()
return _

def AddSuffix(Input):
"""Add a suffix."""
class _(Input):
def set_suffix(self, suffix):
self._suffix = suffix
def run(self):
return super().run() + self._suffix
return _

def PrintOutput(Input):
"""Print message."""
class _(Input):
def run(self):
print(super().run())
return _

PrintPrefixSuffixMessage = PrintOutput(
AddSuffix(AddPrefix(InputMessage))
)
message = PrintPrefixSuffixMessage()
message.set_prefix('Victor says: ')
message.set_suffix(' and goodbye!')
message.run()

我不确定这两种方法之间的区别是否有任何实际意义。目前,我只是想了解他们能表达什么。
跳出递归的兔子洞
我想指出的是,可以在混合中添加递归。这让我们想起了C++中使用的一些元编程技术,使得 computation at compile-time成为可能。原则上,python中没有解释语言的应用程序。
请容我举下一个不切实际的例子。
class Identity:
def run(self, z):
return z

def MandelbrotSeq(Base, n):
def Mandelbrot(Base, n):
if n == 0:
return Base
class _(Base):
def run(self, z):
z = super().run(z)
return z**2 + self.c
return Mandelbrot(_, n-1)
return Mandelbrot(Base, n).__mro__

M = MandelbrotSeq(Identity, 5)

m = M[0]()
m.c = 1
# print 677 the value at 5th iteration for c=1
print(m.run(0))

m = M[1]()
m.c = 1
# print 26 the value at 4th iteration for c=1
print(m.run(0))

m = M[2]()
m.c = 1
# print 5 the value at 3th iteration for c=1
print(m.run(0))

MandelbrotSeq工厂递归地将 Mandelbrot sequence映射为层次连接类的列表m的第一个元素是指身份类的第五代后代。这意味着调用m[0]实例的run(.)成员函数将返回序列的第5个值。同样,我调用m[1]实例的run(.)member函数将返回序列的第4个值。
这只是如何利用python mro的一个极端示例,如前一节所示。这只是一个玩具例子,我没能想出一个比分形更好的主意,仅仅因为涉及递归。请不要在家里这样做!

最佳答案

答案是我根据自己的研究和stackoverflow的一些评论所学到的。
我写了一个关于这些方法的详细博客,叫做Mixin and policy-based design in python。在这篇文章中,我还讨论了几个扩展,比如使用装饰器实现,添加了混合类的默认类,以及更多…
设计要求和实现
要求
设计一个Python模块,这样用户可以通过继承一组预定义的类来创建具有新行为和接口的类这种方法基于用户可以组合成新类的所有可能方式,为用户提供了大量可用的类。
此需求可以使用MIXIN和基于策略的实现来实现。
混和实现
MIXIN的实现定义如下:
模块类在MIXIN和基类之间进行划分。
MIXIN类实现对基类的行为或接口的修改。
用户通过继承将一个或多个MIN(IN)与基类结合来创建一个新类。

class Mixin1Class:
"""Implementation of some Mixin1 class."""
class Mixin2Class:
"""Implementation of some Mixin2 class."""
...
class BasedClass:
"""Implementation of based class."""

# End user creating new class
class NewClass(Mixin1Class, [Mixin2Class, ...], BasedClass):
pass

参考文献:
Wikipedia: Mixin
StackOverflow answer about mixin
基于政策的实施
基于政策的实施定义如下:
模块类分为策略类和主机类。
策略类实现对主机的行为或接口的修改。
宿主类是用类工厂定义的,即返回类型对象的函数。
用户使用类工厂调用新类的创建。
策略类作为参数传递给类工厂。
在类工厂中,宿主类是以所有策略类作为其父类创建的。
class Policy1Class:
"""Implementation of some Policy1 class."""
class Policy2Class:
"""Implementation of some Policy2 class."""
...
def HostClassFactory(Policy1, Policy2=Policy2Class, ...):
"""Create a HostClass and return it."""
class HostClass(Policy1, Policy2, ...):
"""Concrete implementation of the host class."""
return HostClass

# End user invoking new class
NewClass = HostClassFactory(Policy1Class, [Policy2Class,...])

参考文献:
Wikipedia: Modern C++ Design, Policy-based design
My question in stackoverflow
My technical blog: Policy-based design in python
实现之间的比较
这里列出了不同方法之间的区别:
类之间的关系不同,这会影响python的方法解析顺序或mro,请参见下图。
当用户创建新类时,定义或实例化了MIXIN的基类。
但是,基于策略的主机类定义会延迟,直到用户调用factory函数。
可以提供默认的策略类,但不能有MIXIN默认类。

关于python - 有什么措施可以将Python代码称为基于策略的设计?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57365189/

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