Python decorator早期解析会破坏转发声明
我在一个系统中有一些对象,它们需要知道下一个队列是谁。每个类都有一个do_process()函数,完成后必须返回下一个类Python decorator早期解析会破坏转发声明,python,decorator,Python,Decorator,我在一个系统中有一些对象,它们需要知道下一个队列是谁。每个类都有一个do_process()函数,完成后必须返回下一个类 class A(): def do_process(self): # dosomestuff return B(self) class B(): def do_process(self): # dosomestuff return C(self) class C(): def do_p
class A():
def do_process(self):
# dosomestuff
return B(self)
class B():
def do_process(self):
# dosomestuff
return C(self)
class C():
def do_process(self):
# dosomestuff
return A(self)
a = A()
b = a.do_process()
c = b.do_process()
a2 = c.do_process()
然后我注意到我所有的函数在返回时都做同样的事情,我真的应该为此编写一个装饰程序。我想整理一下do_过程中的最后一行,以清楚地表明它将使用装饰器返回以保持清晰,因此它的内容如下:
@next_process(B) # tell the reader up front that the next object is a B thing
def do_process
# do some stuff
# next_process decorator returns an instance of B for us
在我的实现中,构造函数接受几个参数,但总是相同的参数,因为我的代码中的a、B、C重写了基类。一个典型的工厂模式问题。但是,我立即遇到了麻烦,因为装饰程序开始在类A中解析这个,而B还没有声明。我也不擅长编写装饰器,所以我编写了一个工厂,希望用字符串“B”替换B,让工厂在运行时向装饰器提供下一个对象。但这很糟糕,因为我只能在B完全声明后将B类添加到我的工厂中。然而,装饰程序已经想要得到B的一个副本,它实际上在解析a的同时调用了我的工厂,因此它在工厂之前调用了我的工厂,或者任何人实际上知道B(类a本身,在这一点上甚至没有在工厂中注册)
A类()
Next Ext装饰(下一个工厂(B))你应该真正停止用C++术语思考。您几乎不需要编写工厂,通常只需简单的映射即可。提前编写以字符串版本作为参数的装饰器,但在内部使用映射
def next_process(next_):
def deco(func):
def wrapper(self, *args, **kwargs):
func(self, *args, **kwargs)
return MAP[next_](self)
return wrapper
return deco
class Process:
def __init__(self, prev_process):
self.prev_process = prev_process
class A(Process):
@next_process('B')
def do_process(self):
# dosomestuff
return B(self)
class B(Process):
@next_process('C')
def do_process(self):
# dosomestuff
return C(self)
class C(Process):
@next_process('A')
def do_process(self):
# dosomestuff
return A(self)
MAP = {'A': A, 'B':B, 'C':C}
注意,如果您继续创建一些工厂
类,同样的原则也适用。只需在内部使用该工厂。或者不要急于对其进行评估。只需按相反的顺序定义它们?@juanpa.arrivillaga这是我简单的直接解决方案,就是这样做的。这些类是selenium页面对象,我不想被困在创建引用圈的过程中,因此工厂模式就像是一条尝试的路线。谢谢@juanpa。这正是我想要的,我的解释要么还可以,要么你很擅长拼图。在我遗漏的基类上扩展的额外分数。我的应用程序中的每个类都是一个Selenium页面对象,因此我需要一个装饰器,以便一个页面指向另一个页面<代码>@next_process('A')def do_process(self):#dosomestuff返回self#
def next_process(next_):
def deco(func):
def wrapper(self, *args, **kwargs):
func(self, *args, **kwargs)
return MAP[next_](self)
return wrapper
return deco
class Process:
def __init__(self, prev_process):
self.prev_process = prev_process
class A(Process):
@next_process('B')
def do_process(self):
# dosomestuff
return B(self)
class B(Process):
@next_process('C')
def do_process(self):
# dosomestuff
return C(self)
class C(Process):
@next_process('A')
def do_process(self):
# dosomestuff
return A(self)
MAP = {'A': A, 'B':B, 'C':C}