简体   繁体   English

程序创建的装饰函数

[英]Procedurally created decorator functions

My goal is to create a function that will procedurally generate a series of other functions within a class from serialized data. 我的目标是创建一个函数,该函数将在序列化数据的过程中从程序上生成一系列其他函数。 This is easy enough using dict , but... i would like for each function to be initialized with the @property decorator (or a similar custom decorator) so that i can call these functions like attributes 这很容易使用dict ,但是...我想用@property装饰器(或类似的自定义装饰器)初始化每个函数,这样我就可以像属性一样调用这些函数

Basically, I would like to do something like the following: 基本上,我想做类似以下的事情:

class myClass(object):
    def __init__(self):
        self.makeFuncs(['edgar','allan','poe'])

    def makeFuncs(self, data):
        for item in data:
            self.__dict__[item] = '[%s] <--- is_the_data' % item 

myInstance = myClass()
print myInstance.poe
#'[poe] <--- is_the_data'

Got any Ideas? 有什么想法?

You can dynamically add property s, but properties are added to the class object, not the instance. 您可以动态添加property ,但属性将添加到对象,而不是实例。

Here's an example: 这是一个例子:

def make_prop(cls, p):
    def f(self):
        print 'IN %s' % p
        return '[%s]' % p
    return f    

class myClass(object):
  pass

# add the properties
for p in ('edgar','allan','poe'):
    setattr(myClass, p, property(make_prop(myClass, p)))

y = myClass()
print y.a
print y.b

Prints: 打印:

IN allan
[allan]
IN poe
[poe]

Also, it is essential to use make_prop to create the function object, instead of creating them directly inside the for loop, due to python's lexical scoping. 此外,由于python的词法作用域,必须使用make_prop来创建函数对象,而不是直接在for循环中创建它们。 Ie this won't work as expected : 这不会按预期工作

# add the properties
for p in ('edgar','allan','poe'):
    def f(self):
        print 'IN %s' % p
        return '[%s]' % p
    setattr(myClass, p, property(f))

Here is the answer I came to for procedurally adding properties to a custom shader class in maya. 下面是我为在maya中自定义着色器类的过程添加属性而给出的答案。

Thx @shx2 ! 谢谢@ shx2!

import maya.cmds as mc
import sushi.maya.node.dependNode as dep

class Shader(dep.DependNode):
    def __init__(self, *args, **kwargs):
        super(Shader, self).__init__(*args, **kwargs)
        makeProps(self.__class__, ['color','transparency','ambientColor','incandescence','diffuse','translucence','translucenceDepth','translucenceFocus'])

def createShaderProperties(attrName):
    def getterProp(self):
        return mc.getAttr('%s.%s' % (self.name, attrName))[0]
    def setterProp(self, value):
        mc.setAttr('%s.%s' % (self.name, attrName), *value, type = 'double3')
    return (getterProp, setterProp)

def makeProps(cls, data):
    for dat in data:
        getterProp, setterProp = createShaderProperties(dat)
        setattr(cls, dat, property(getterProp))
        setattr(cls, dat, property.setter(cls.__dict__[dat],setterProp))

Your current idea won't work because property objects need to be in the class in order to work (they are descriptors ). 您当前的想法将无法工作,因为property对象需要在类中才能工作(它们是描述符 )。 Since your list of functions is specific to each instance, that won't be possible. 由于您的函数列表特定于每个实例,因此无法实现。

However, you can make the general idea work using __getattr__ . 但是,您可以使用__getattr__使一般想法工作。 Here's an implementation that I think does what you want given a dictionary mapping from names to functions: 这是一个实现,我认为你可以根据名称到函数的字典映射做到这一点:

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

    def __getattr__(self, name):
        if name in self.func_dict:
            return self.func_dict[name]()     # call the function

        raise AttributeError("{} object has no attribute named {}"
                             .format(self.__class__.__name__, name)) # or raise an error

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM