装饰师是正确的用法吗? [英] is decorator the right thing to use?

查看:54
本文介绍了装饰师是正确的用法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




听了很多关于装饰器的事情,从来没有真正使用过我的

决定尝试一下。我特别使用的是,我有类

作为其他类的代理(即将消息传递给那些

类)但是手工编码这类类是相当乏味,所以我

决定使用装饰器。有人可以告诉我,我正在做什么

是一个潜在的脚步还是我在正确的轨道上? (注意,它是

而不是基本的概念验证实现,而不是最终的

解决方案我将要使用所以没有优化或

签名保留代码,只是想法)。


这里是代码:


A级:

b =无

def __init __(自我,b):

self.val =''aval''

self.b = b

b.val =''aval''


def mymethod(self,a):

print" A :: mymethod,",

def mymethod2(self,a):

print" A ::另一种方法,,一个

def Aproxy(fn):

def delegate(* args,** kw):

print" ;%的s ::%S" %(args [0] .__ class __.__ name __,fn .__ name__)

args = list(args)

b = getattr(args [0],'b'' )

fnew = getattr(b,fn .__ name__)

#摆脱原始对象引用

del args [0]

fnew(* args,** kw)

setattr(A,fn .__ name __,delegate)

返回fn


B级:

def __init __(个体经营):

self.val =''bval''


@Aproxy

def bmethod(self,a):

print" B :: bmethod"

print a,self.val


@Aproxy

def bmethod2(self,a):

print" B :: bmethod2"

打印a,self.val


b = B()

b.bmethod(''foo'')

a = A(b)

b = B()

b.val =''newval''

a.bmethod(''bar' ')

a.bmethod2(''zam'')

解决方案

9月24日,3:21 * pm ,Dmitry S. Makovey, < dmi ... @ athabascau.cawrote:





听了很多关于装饰器的事情,实际上从来没有使用一个我有一个b $ b决定尝试一下。我特别使用的是,我有类

作为其他类的代理(即将消息传递给那些

类)但是手工编码这类类是相当乏味,所以我

决定使用装饰器。有人可以告诉我,我正在做什么

是一个潜在的脚步还是我在正确的轨道上? (注意,它是

而不是基本的概念验证实现,而不是最终的

解决方案我将要使用所以没有优化或

签名保留代码,只是想法)。



下面你的代码非常抽象,所以它有点难弄清楚

你试图解决什么问题,但在我看来你是使用B代理类来装饰A目标类的
,这意味着

你想要其中一个选项:


1)将装饰器放在A中的方法上,而不是B.不是吗? br />
在这里装饰A的方法?


2)消除装饰器语法并使你的代码更多

表达:


a = SomeClass()

#先直接调用

x = a.foo()

y = a.bar()

#现在装饰它

debug_proxy =

ClassThatDecoratesMethodCa llsToObjectWithDebugging代码(a)

debug_proxy.decorate_methods(''foo'',''bar'')


decorate_methods方法将是神奇的,就其而言覆盖

a'的内脏,同时仍然为其用户保留相同的界面。


但是,我只是猜测在这里,因为很难知道你真正解决了什么问题。


干杯,


史蒂夫


以下代码引用:


这里是代码:


等级A:

* * b =无

* * def __init __(self,b):

* * * * self。 val =''aval''

* * * * self.b = b

* * * * b.val =''aval''


* * def mymethod(self,a):

* * * * print" A :: mymethod," a


* * def mymethod2(self,a):

* * * * print" A :: another method," a

高清Aproxy(fn):

* * def delegate(* args,** kw):

* * * * print"%s ::%s" %(args [0] .__ class __.__ name __,fn .__ name__)

* * * * args = list(args)

* * * * b = getattr(args) [0],''b'')

* * * * fnew = getattr(b,fn .__ name__)

* * * *#摆脱原始对象参考

* * * * del args [0]

* * * * fnew(* args,** kw)

* * setattr (A,fn .__姓名__,代表)

* *返回fn


B级:

* * def __init __(自我):

* * * * self.val =''bval''


* * @Aproxy

* * def bmethod(self,a):

* * * * print" B :: bmethod"

* * * * print a,self.val


* * @Aproxy

* * def bmethod2(self,a):

* * * * print" B :: bmethod2"

* * * *打印a,self.val


b = B()

b.bmethod(''foo'' )

a = A(b)

b = B()

b.val =''newval''

a.bmethod(''bar'')

a.bmethod2(''zam'')


sh ********** **@gmail.com 写道:


下面的代码非常抽象,所以很难搞清楚

你试图解决什么问题,但在我看来你是用b代理类来装饰A目标类,这意味着


您想要以下选项之一:



对不起原始帖子中的不明之处。基本上是一个聚合对象

B级(没有装饰者的例子,而且过于简化了):


A级:

b =无

def __init __(self,b):

self.b = b


def amethod(self, a):

打印A :: amethod,


打印A :: bmethod,a

返回self.b.bmethod(a)


def bmethod2(self,a,z):

打印" A :: bmethod2",a,z

返回self.b.bmethod2(a,z)

class B :

def __init __(自我):

self.val = a


def bmethod(self,a):

print" B :: bmethod",a

def bmethod2(self,a,z):

print" B :: bmethod2",a,z

b = B()

a = A(b)

a.bmethod(''foo '')

a.bmethod2(''bar'',''baz'')


在我的现实案例中,A是代理B,C和D实例/对象,n只需

一个。如果你看一下上面的代码 - 无论何时我在B中写入新方法,C

或DI都要修改A,或者甚至当我修改签名时(比如说,添加

) B,C或DI中的参数x到bmethod)必须确保A是同步的。

我希望使用装饰器为我自动完成。由于

结果代码对于所有这些代理方法几乎都是相同的,因此它似乎是自动化的好地方。或者我错了,假设那个?

(因为这是我第一次使用装饰师,老实说我也不知道)


上面提到的代码说明了我的意思现在就做我原来的帖子

是为了让事情更加自动化/万无一失。


Dmitry S. Makovey写道:


在我的现实案例中,A是B,C和D实例/对象的代理,而不是

只有一个。



忘了提到上面的意思是我需要有多个

装饰器函数,比如AproxyB,AproxyC和AproxyD,或者制作Aproxy更聪明

关于A的哪个属性具有哪个等级的实例等。


除非我完全出去吃午饭并且有更好的方法来实现

这个(除了B,C或D

中的任何内容发生变化时复制粘贴的东西)。


Hi,

after hearing a lot about decorators and never actually using one I have
decided to give it a try. My particular usecase is that I have class that
acts as a proxy to other classes (i.e. passes messages along to those
classes) however hand-coding this type of class is rather tedious, so I
decided to use decorator for that. Can somebody tell me if what I''m doing
is a potential shot-in-the-foot or am I on the right track? (Note, It''s
rather rudimentary proof-of-concept implementation and not the final
solution I''m about to employ so there are no optimizations or
signature-preserving code there yet, just the idea).

Here''s the code:

class A:
b=None
def __init__(self,b):
self.val=''aval''
self.b=b
b.val=''aval''

def mymethod(self,a):
print "A::mymethod, ",a

def mymethod2(self,a):
print "A::another method, ",a
def Aproxy(fn):
def delegate(*args,**kw):
print "%s::%s" % (args[0].__class__.__name__,fn.__name__)
args=list(args)
b=getattr(args[0],''b'')
fnew=getattr(b,fn.__name__)
# get rid of original object reference
del args[0]
fnew(*args,**kw)
setattr(A,fn.__name__,delegate)
return fn

class B:
def __init__(self):
self.val=''bval''

@Aproxy
def bmethod(self,a):
print "B::bmethod"
print a, self.val

@Aproxy
def bmethod2(self,a):
print "B::bmethod2"
print a, self.val

b=B()
b.bmethod(''foo'')
a=A(b)
b=B()
b.val=''newval''
a.bmethod(''bar'')
a.bmethod2(''zam'')

解决方案

On Sep 24, 3:21*pm, "Dmitry S. Makovey" <dmi...@athabascau.cawrote:

Hi,

after hearing a lot about decorators and never actually using one I have
decided to give it a try. My particular usecase is that I have class that
acts as a proxy to other classes (i.e. passes messages along to those
classes) however hand-coding this type of class is rather tedious, so I
decided to use decorator for that. Can somebody tell me if what I''m doing
is a potential shot-in-the-foot or am I on the right track? (Note, It''s
rather rudimentary proof-of-concept implementation and not the final
solution I''m about to employ so there are no optimizations or
signature-preserving code there yet, just the idea).

Your code below is very abstract, so it''s kind of hard to figure out
what problem you''re trying to solve, but it seems to me that you''re
using the B proxy class to decorate the A target class, which means
you want one of these options:

1) Put decorators over the methods in A, not B. Isn''t it the
methods of A that are being decorated here?

2) Eliminate the decorator syntax and make your code more
expressive:

a = SomeClass()
# first call it directly
x = a.foo()
y = a.bar()
# now decorate it
debug_proxy =
ClassThatDecoratesMethodCallsToObjectWithDebugging Code(a)
debug_proxy.decorate_methods(''foo'', ''bar'')

The decorate_methods method would be magical, in terms of overwriting
a''s innards, while still preserving the same interface for its users.

But again, I''m just guessing here, because it''s hard to know what
problem you''re really solving.

Cheers,

Steve

Code quoted below:

Here''s the code:

class A:
* * b=None
* * def __init__(self,b):
* * * * self.val=''aval''
* * * * self.b=b
* * * * b.val=''aval''

* * def mymethod(self,a):
* * * * print "A::mymethod, ",a

* * def mymethod2(self,a):
* * * * print "A::another method, ",a

def Aproxy(fn):
* * def delegate(*args,**kw):
* * * * print "%s::%s" % (args[0].__class__.__name__,fn.__name__)
* * * * args=list(args)
* * * * b=getattr(args[0],''b'')
* * * * fnew=getattr(b,fn.__name__)
* * * * # get rid of original object reference
* * * * del args[0]
* * * * fnew(*args,**kw)
* * setattr(A,fn.__name__,delegate)
* * return fn

class B:
* * def __init__(self):
* * * * self.val=''bval''

* * @Aproxy
* * def bmethod(self,a):
* * * * print "B::bmethod"
* * * * print a, self.val

* * @Aproxy
* * def bmethod2(self,a):
* * * * print "B::bmethod2"
* * * * print a, self.val

b=B()
b.bmethod(''foo'')
a=A(b)
b=B()
b.val=''newval''
a.bmethod(''bar'')
a.bmethod2(''zam'')


sh************@gmail.com wrote:

Your code below is very abstract, so it''s kind of hard to figure out
what problem you''re trying to solve, but it seems to me that you''re
using the B proxy class to decorate the A target class, which means
you want one of these options:

Sorry for unclarities in original post. Basically A aggregates object of
class B (example with no decorators and again it''s oversimplified):

class A:
b=None
def __init__(self,b):
self.b=b

def amethod(self,a):
print "A::amethod ", a

def bmethod(self,a):
print "A::bmethod ",a
return self.b.bmethod(a)

def bmethod2(self,a,z):
print "A::bmethod2 ",a,z
return self.b.bmethod2(a,z)
class B:
def __init__(self):
self.val=a

def bmethod(self,a):
print "B::bmethod ",a

def bmethod2(self,a,z):
print "B::bmethod2 ",a,z
b=B()
a=A(b)
a.bmethod(''foo'')
a.bmethod2(''bar'',''baz'')

In my real-life case A is a proxy to B, C and D instances/objects, not just
one. If you look at above code - whenever I write new method in either B, C
or D I have to modify A, or even when I modify signature (say, add
parameter x to bmethod) in B, C or D I have to make sure A is synchronized.
I was hoping to use decorator to do it automatically for me. Since the
resulting code is virtually all the same for all those proxy methods it
seems to be a good place for automation. Or am I wrong assuming that?
(since it is my first time using decorators I honestly don''t know)

Abovementioned code ilustrates what I am doing right now. My original post
is an attempt to make things more automated/foolproof.


Dmitry S. Makovey wrote:

In my real-life case A is a proxy to B, C and D instances/objects, not
just one.

forgot to mention that above would mean that I need to have more than one
decorator function like AproxyB, AproxyC and AproxyD or make Aproxy smarter
about which property of A has instance of which class etc.

Unless I''m totally "out for lunch" and there are better ways of implementing
this (other than copy-pasting stuff whenever anything in B, C or D
changes).


这篇关于装饰师是正确的用法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆