【问题标题】:Procedurally created decorator functions程序创建的装饰器函数
【发布时间】:2014-03-08 07:36:46
【问题描述】:

我的目标是创建一个函数,该函数将在一个类中从序列化数据中按程序生成一系列其他函数。 这很容易使用 dict ,但是...... 我希望使用@property 装饰器(或类似的自定义装饰器)初始化每个函数,以便我可以像属性一样调用这些函数

基本上,我想做如下的事情:

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'

有什么想法吗?

【问题讨论】:

  • 我不明白你的问题是什么。您的代码已经按照您说的去做,而且您根本没有在那里创建任何功能。您想要的功能和/或属性以什么方式涉及?
  • 现在为了得到正确的返回值,我需要使用 myInstance.poe() 我只是希望像使用 @property 一样使用 myInstance.poe
  • 您编写的代码返回带有myInstance.poe 的值。访问poe 数据不涉及任何函数。您希望以何种方式参与功能?
  • 我认为使用“功能”这个词可能是用词不当。 \我只是想避免使用方括号 ()
  • 就像使用 @property 装饰器时一样

标签: python properties decorator procedural


【解决方案1】:

您可以动态添加propertys,但属性会添加到对象,而不是实例。

这是一个例子:

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

打印:

IN allan
[allan]
IN poe
[poe]

此外,由于 python 的词法作用域,必须使用 make_prop 创建函数对象,而不是直接在 for 循环内创建它们。 IE。 这不会按预期工作

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

【讨论】:

  • wait.. 'make_prop' 应该是 'myClass' 中的一个函数吗? 'cls' 应该是 'self' 吗?
  • 很高兴我能帮上忙!随意投票和/或接受有用的答案
  • 我不能......这是我的第一篇文章......我没有代表......但是当我这样做时,我会为你投票,我保证
【解决方案2】:

这是我在程序上将属性添加到 Maya 中的自定义着色器类的答案。

谢谢@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))

【讨论】:

    【解决方案3】:

    您当前的想法行不通,因为property 对象需要在类中才能工作(它们是descriptors)。由于您的函数列表特定于每个实例,因此这是不可能的。

    但是,您可以使用__getattr__ 使总体思路发挥作用。这是一个实现,我认为在给定从名称到函数的字典映射的情况下,它可以满足您的需求:

    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
    

    【讨论】:

    • 神圣的 S#$i$%。这是我的第一篇文章。你们在 30 秒内解决了我的问题……太棒了。谢谢。
    • hmmm...实际上..不..这行不通,因为“func_dict”中的func无权访问类实例中的“self”,除非functools?.....虽然看起来很乱
    • 如果不清楚...我正在尝试在类或实例的上下文中定义函数...如果有意义的话。
    • @Pax:如果您愿意,可以在从__getattr__ 调用函数时传递函数self。如有必要,您也可以传递其他参数,但我不确定这是否有意义。
    猜你喜欢
    • 2020-06-20
    • 2021-06-22
    • 2014-02-13
    • 2014-01-25
    • 2019-06-16
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 2018-05-26
    相关资源
    最近更新 更多