setattr 和 getattr 方法

setattr and getattr with methods

我有一个 boiler platey class 将一些操作委托给引用 class。它看起来像这样:

class MyClass():

    def __init__(self, someClass):            
        self.refClass = someClass

    def action1(self):
        self.refClass.action1()

    def action2(self):
        self.refClass.action2()

    def action3(self):
        self.refClass.action3()

这是 refClass:

class RefClass():

    def __init__(self):
        self.myClass = MyClass(self)

    def action1(self):
        #Stuff to execute action1

    def action2(self):
        #Stuff to execute action2

    def action3(self):
        #Stuff to execute action3

我想使用 Python 元编程来使其更加优雅和可读,但我不确定如何使用。

我听说过setattr and getattr,我想我可以做类似

的事情
class MyClass():

    def __init__(self, someClass):            
        self.refClass = someClass

    for action in ['action1', 'action2', 'action3']:
        def _delegate(self):
            getattr(self.refClass, action)()

然后我知道我需要从某个地方做这件事,我想:

MyClass.setattr(action, delegate)

我就是不能完全理解这个概念。我了解关于不重复代码以及使用函数式编程使用 for 循环生成方法的基础知识,但我不知道如何从其他地方调用这些方法。嘻嘻!

就个人而言,对于委派事情,我通常会这样做:

def delegate(prop_name, meth_name):
    def proxy(self, *args, **kwargs):
        prop = getattr(self, prop_name)
        meth = getattr(prop, meth_name)
        return meth(*args, **kwargs)
    return proxy

class MyClass(object):
    def __init__(self, someClass):
        self.refClass = someClass

    action1 = delegate('refClass', 'action1')
    action2 = delegate('refClass', 'action2')

这将创建您需要的所有委托方法:)

对于某些解释,此处的委托函数只是创建一个 "proxy" 函数,它将充当 class 方法(请参阅 self 参数?)并将传递给定的所有参数使用 argskwargs 参数将其传递给引用对象的方法(有关这些参数的更多信息,请参阅 *args and **kwargs?

你也可以用列表创建它,但我更喜欢第一个,因为它对我来说更明确:)

class MyClass(object):
    delegated_methods = ['action1', 'action2']

    def __init__(self, someClass):
        self.refClass = someClass

        for meth_name in self.delegated_methods:
            setattr(self, meth_name, delegate('refClass', meth_name))

Python 已经包含对包含的 class 的广义委派的支持。只需将 MyClass 的定义更改为:

class MyClass:

    def __init__(self, someClass):            
        self.refClass = someClass  # Note: You call this someClass, but it's actually some object, not some class in your example

    def __getattr__(self, name):
        return getattr(self.refClass, name)

定义后,__getattr__ is called on the instance with the name of the accessed attribute any time an attribute is not found on the instance itself. You then delegate to the contained object by calling getattr 查找包含对象的属性并 return 它。每次动态查找都会消耗一点点,所以如果你想避免它,你可以在 __getattr__ 第一次请求属性时延迟缓存属性,因此后续访问是直接的:

def __getattr__(self, name):
     attr = getattr(self.refClass, name)
     setattr(self, name, attr)
     return attr