代码之家  ›  专栏  ›  技术社区  ›  Anthony Kong

如何动态地将属性添加到类中?

  •  167
  • Anthony Kong  · 技术社区  · 16 年前

    目标是创建一个行为类似于db resultset的模拟类。

    例如,如果数据库查询返回,使用dict表达式, {'ab':100, 'cd':200} ,那么我想看看:

    >>> dummy.ab
    100
    

    起初我想我可以这样做:

    ks = ['ab', 'cd']
    vs = [12, 34]
    class C(dict):
        def __init__(self, ks, vs):
            for i, k in enumerate(ks):
                self[k] = vs[i]
                setattr(self, k, property(lambda x: vs[i], self.fn_readyonly))
    
        def fn_readonly(self, v)
            raise "It is ready only"
    
    if __name__ == "__main__":
        c = C(ks, vs)
        print c.ab
    

    但是 c.ab 返回属性对象。

    替换 setattr 用线 k = property(lambda x: vs[i]) 根本没用。

    那么,在运行时创建实例属性的正确方法是什么?

    P.S.我知道 How is the __getattribute__ method used?

    20 回复  |  直到 7 年前
        1
  •  274
  •   Eevee    13 年前

    我想我应该扩大这个答案,因为我已经长大了,更聪明了,知道发生了什么事。迟到总比不迟到好。

    可以 动态向类添加属性。但这就是关键:你必须把它添加到 .

    >>> class Foo(object):
    ...     pass
    ... 
    >>> foo = Foo()
    >>> foo.a = 3
    >>> Foo.b = property(lambda self: self.a + 1)
    >>> foo.b
    4
    

    property 实际上是一个叫做 descriptor .它是为给定属性提供自定义处理的对象, 在给定的类上 .有点像是一种将 if 树出 __getattribute__ .

    当我要求 foo.b 在上面的示例中,python看到 b 在类上定义的实现 描述符协议 这意味着它是一个物体 __get__ , __set__ ,或 __delete__ 方法。描述符声称负责处理该属性,所以python调用 Foo.b.__get__(foo, Foo) ,返回值作为属性的值返回给您。在情况下 财产 ,每个方法只调用 fget , fset ,或 fdel 你传给了 财产 构造函数。

    描述符实际上是Python公开其整个OO实现的管道的方法。实际上,还有另一种类型的描述符比 财产 .

    >>> class Foo(object):
    ...     def bar(self):
    ...         pass
    ... 
    >>> Foo().bar
    <bound method Foo.bar of <__main__.Foo object at 0x7f2a439d5dd0>>
    >>> Foo().bar.__get__
    <method-wrapper '__get__' of instancemethod object at 0x7f2a43a8a5a0>
    

    谦虚的方法只是另一种描述符。它的 第二代 将调用实例附加为第一个参数;实际上,它执行以下操作:

    def __get__(self, instance, owner):
        return functools.partial(self.function, instance)
    

    不管怎样,我怀疑这就是为什么描述符只在类上工作的原因:它们首先是为类提供动力的东西的形式化。它们甚至是规则的例外:显然可以将描述符分配给类,而类本身就是 type !事实上,尝试阅读 Foo.b 仍然通话 property.__get__ ;对于描述符来说,当作为类属性访问时返回自己是惯用的方法。

    我认为,几乎所有Python的OO系统都可以用Python表示,这很酷。:)

    哦,我写了一篇 wordy blog post about descriptors 如果你感兴趣的话。

        2
  •  51
  •   bobince    16 年前

    目标是创建一个行为类似于db resultset的模拟类。

    所以你想要的是一本字典,你可以把a['b']拼成a.b?

    这很容易:

    class atdict(dict):
        __getattr__= dict.__getitem__
        __setattr__= dict.__setitem__
        __delattr__= dict.__delitem__
    
        3
  •  33
  •   Eevee    14 年前

    似乎你可以更简单地用 namedtuple ,因为您提前知道整个字段列表。

    from collections import namedtuple
    
    Foo = namedtuple('Foo', ['bar', 'quux'])
    
    foo = Foo(bar=13, quux=74)
    print foo.bar, foo.quux
    
    foo2 = Foo()  # error
    

    如果您绝对需要编写自己的setter,则必须在类级别上执行元编程; property() 不适用于实例。

        4
  •  28
  •   pppery gumboy    10 年前

    你不需要使用一个属性。只是超越 __setattr__ 使它们只读。

    class C(object):
        def __init__(self, keys, values):
            for (key, value) in zip(keys, values):
                self.__dict__[key] = value
    
        def __setattr__(self, name, value):
            raise Exception("It is read only!")
    

    Tada。

    >>> c = C('abc', [1,2,3])
    >>> c.a
    1
    >>> c.b
    2
    >>> c.c
    3
    >>> c.d
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'C' object has no attribute 'd'
    >>> c.d = 42
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 6, in __setattr__
    Exception: It is read only!
    >>> c.a = 'blah'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 6, in __setattr__
    Exception: It is read only!
    
        5
  •  5
  •   Community Mohan Dere    8 年前

    我问了一个类似的问题 on this Stack Overflow post 创建创建简单类型的类工厂。结果是 this answer 它有一个类工厂的工作版本。 下面是一小段答案:

    def Struct(*args, **kwargs):
        def init(self, *iargs, **ikwargs):
            for k,v in kwargs.items():
                setattr(self, k, v)
            for i in range(len(iargs)):
                setattr(self, args[i], iargs[i])
            for k,v in ikwargs.items():
                setattr(self, k, v)
    
        name = kwargs.pop("name", "MyStruct")
        kwargs.update(dict((k, None) for k in args))
        return type(name, (object,), {'__init__': init, '__slots__': kwargs.keys()})
    
    >>> Person = Struct('fname', 'age')
    >>> person1 = Person('Kevin', 25)
    >>> person2 = Person(age=42, fname='Terry')
    >>> person1.age += 10
    >>> person2.age -= 10
    >>> person1.fname, person1.age, person2.fname, person2.age
    ('Kevin', 35, 'Terry', 32)
    >>>
    

    您可以使用这个变量来创建默认值,这是您的目标(这个问题中还有一个解决这个问题的答案)。

        6
  •  5
  •   Aaron Hall    9 年前

    如何向python类动态添加属性?

    假设您有一个要向其添加属性的对象。通常,我希望在需要开始管理对具有下游用法的代码中的属性的访问时使用属性,以便维护一致的API。现在,我通常会将它们添加到定义对象的源代码中,但假设您没有该访问权限,或者您需要真正以编程方式动态地选择函数。

    创建一个类

    使用基于 documentation for property ,让我们创建一个具有“hidden”属性的对象类,并创建它的实例:

    class C(object):
        '''basic class'''
        _x = None
    
    o = C()
    

    在Python中,我们希望有一种明显的方式来做事情。但是,在本例中,我将展示两种方法:使用decorator符号,不使用decorator符号。首先,没有装饰符号。这对于getter、setter或deleter的动态分配可能更有用。

    动态(即猴子修补)

    让我们为我们的班级创建一些:

    def getx(self):
        return self._x
    
    def setx(self, value):
        self._x = value
    
    def delx(self):
        del self._x
    

    现在我们把这些转让给地产。注意,我们可以在这里以编程方式选择函数,回答动态问题:

    C.x = property(getx, setx, delx, "I'm the 'x' property.")
    

    用途:

    >>> o.x = 'foo'
    >>> o.x
    'foo'
    >>> del o.x
    >>> print(o.x)
    None
    >>> help(C.x)
    Help on property:
    
        I'm the 'x' property.
    

    装饰者

    我们可以像上面用decorator符号所做的那样,但是在本例中,我们 必须 将方法命名为所有相同的名称(我建议将其保持与属性相同),因此编程分配不像使用上述方法那样简单:

    @property
    def x(self):
        '''I'm the 'x' property.'''
        return self._x
    
    @x.setter
    def x(self, value):
        self._x = value
    
    @x.deleter
    def x(self):
        del self._x
    

    并将属性对象及其设置的setter和deleter分配给类:

    C.x = x
    

    用途:

    >>> help(C.x)
    Help on property:
    
        I'm the 'x' property.
    
    >>> o.x
    >>> o.x = 'foo'
    >>> o.x
    'foo'
    >>> del o.x
    >>> print(o.x)
    None
    
        7
  •  5
  •   martineau    8 年前

    不能添加新的 property() 在运行时传递给实例,因为属性是数据描述符。相反,您必须动态地创建一个新类或重载 __getattribute__ 以便处理实例上的数据描述符。

        8
  •  3
  •   Crescent Fresh    16 年前

    不确定我是否完全理解这个问题,但是您可以在运行时使用内置的 __dict__ 你们班:

    class C(object):
        def __init__(self, ks, vs):
            self.__dict__ = dict(zip(ks, vs))
    
    
    if __name__ == "__main__":
        ks = ['ab', 'cd']
        vs = [12, 34]
        c = C(ks, vs)
        print(c.ab) # 12
    
        9
  •  3
  •   tleb Paul R    8 年前

    对于那些来自搜索引擎的人,这是我在谈论的两件事 动态 性能:

    class Foo:
        def __init__(self):
            # we can dynamically have access to the properties dict using __dict__
            self.__dict__['foo'] = 'bar'
    
    assert Foo().foo == 'bar'
    
    
    # or we can use __getattr__ and __setattr__ to execute code on set/get
    class Bar:
        def __init__(self):
            self._data = {}
        def __getattr__(self, key):
            return self._data[key]
        def __setattr__(self, key, value):
            self._data[key] = value
    
    bar = Bar()
    bar.foo = 'bar'
    assert bar.foo == 'bar'
    

    __dict__ 如果要放置动态创建的属性,则很好。 __getattr__ 只在需要值时才执行某些操作,例如查询数据库。set/get组合有助于简化对类中存储的数据的访问(如上面的示例)。

    如果只需要一个动态属性,请查看 property() 内置功能。

        10
  •  2
  •   nosklo    16 年前

    最好的方法是通过定义 __slots__ . 这样您的实例就不能有新的属性。

    ks = ['ab', 'cd']
    vs = [12, 34]
    
    class C(dict):
        __slots__ = []
        def __init__(self, ks, vs): self.update(zip(ks, vs))
        def __getattr__(self, key): return self[key]
    
    if __name__ == "__main__":
        c = C(ks, vs)
        print c.ab
    

    那张照片 12

        c.ab = 33
    

    这样就可以: AttributeError: 'C' object has no attribute 'ab'

        11
  •  2
  •   lehins Michael Shigorin    12 年前

    又一个如何达到预期效果的例子

    class Foo(object):
    
        _bar = None
    
        @property
        def bar(self):
            return self._bar
    
        @bar.setter
        def bar(self, value):
            self._bar = value
    
        def __init__(self, dyn_property_name):
            setattr(Foo, dyn_property_name, Foo.bar)
    

    现在我们可以做如下的事情:

    >>> foo = Foo('baz')
    >>> foo.baz = 5
    >>> foo.bar
    5
    >>> foo.baz
    5
    
        12
  •  0
  •   David X    16 年前

    这似乎可行(但见下文):

    class data(dict,object):
        def __init__(self,*args,**argd):
            dict.__init__(self,*args,**argd)
            self.__dict__.update(self)
        def __setattr__(self,name,value):
            raise AttributeError,"Attribute '%s' of '%s' object cannot be set"%(name,self.__class__.__name__)
        def __delattr__(self,name):
            raise AttributeError,"Attribute '%s' of '%s' object cannot be deleted"%(name,self.__class__.__name__)
    

    如果您需要更复杂的行为,请随意编辑您的答案。

    编辑

    对于大型数据集,以下内容可能更节省内存:

    class data(dict,object):
        def __init__(self,*args,**argd):
            dict.__init__(self,*args,**argd)
        def __getattr__(self,name):
            return self[name]
        def __setattr__(self,name,value):
            raise AttributeError,"Attribute '%s' of '%s' object cannot be set"%(name,self.__class__.__name__)
        def __delattr__(self,name):
            raise AttributeError,"Attribute '%s' of '%s' object cannot be deleted"%(name,self.__class__.__name__)
    
        13
  •  0
  •   Aaron Hall    11 年前

    要回答问题的主要内容,您需要将dict中的只读属性作为不可变的数据源:

    目标是创建一个行为类似于db resultset的模拟类。

    例如,如果数据库查询返回,使用dict表达式, {'ab':100, 'cd':200} ,那么我想看看

    >>> dummy.ab
    100
    

    我将演示如何使用 namedtuple collections 完成以下任务的模块:

    import collections
    
    data = {'ab':100, 'cd':200}
    
    def maketuple(d):
        '''given a dict, return a namedtuple'''
        Tup = collections.namedtuple('TupName', d.keys()) # iterkeys in Python2
        return Tup(**d)
    
    dummy = maketuple(data)
    dummy.ab
    

    收益率 100

        14
  •  0
  •   Serhii Khachko    9 年前
    class atdict(dict):
      def __init__(self, value, **kwargs):
        super().__init__(**kwargs)
        self.__dict = value
    
      def __getattr__(self, name):
        for key in self.__dict:
          if type(self.__dict[key]) is list:
            for idx, item in enumerate(self.__dict[key]):
              if type(item) is dict:
                self.__dict[key][idx] = atdict(item)
          if type(self.__dict[key]) is dict:
            self.__dict[key] = atdict(self.__dict[key])
        return self.__dict[name]
    
    
    
    d1 = atdict({'a' : {'b': [{'c': 1}, 2]}})
    
    print(d1.a.b[0].c)
    

    输出为:

    >> 1
    
        15
  •  0
  •   Anthony Holloman    8 年前

    可以使用以下代码使用Dictionary对象更新类属性:

    class ExampleClass():
        def __init__(self, argv):
            for key, val in argv.items():
                self.__dict__[key] = val
    
    if __name__ == '__main__':
        argv = {'intro': 'Hello World!'}
        instance = ExampleClass(argv)
        print instance.intro
    
        16
  •  0
  •   asterio gonzalez    7 年前

    kjfletch

    # This is my humble contribution, extending the idea to serialize
    # data from and to tuples, comparison operations and allowing functions
    # as default values.
    
    def Struct(*args, **kwargs):
        FUNCTIONS = (types.BuiltinFunctionType, types.BuiltinMethodType, \
                     types.FunctionType, types.MethodType)
        def init(self, *iargs, **ikwargs):
            """Asume that unamed args are placed in the same order than
            astuple() yields (currently alphabetic order)
            """
            kw = list(self.__slots__)
    
            # set the unnamed args
            for i in range(len(iargs)):
                k = kw.pop(0)
                setattr(self, k, iargs[i])
    
            # set the named args
            for k, v in ikwargs.items():
                setattr(self, k, v)
                kw.remove(k)
    
            # set default values
            for k in kw:
                v = kwargs[k]
                if isinstance(v, FUNCTIONS):
                    v = v()
                setattr(self, k, v)
    
        def astuple(self):
            return tuple([getattr(self, k) for k in self.__slots__])
    
        def __str__(self):
            data = ['{}={}'.format(k, getattr(self, k)) for k in self.__slots__]
            return '<{}: {}>'.format(self.__class__.__name__, ', '.join(data))
    
        def __repr__(self):
            return str(self)
    
        def __eq__(self, other):
            return self.astuple() == other.astuple()
    
        name = kwargs.pop("__name__", "MyStruct")
        slots = list(args)
        slots.extend(kwargs.keys())
        # set non-specific default values to None
        kwargs.update(dict((k, None) for k in args))
    
        return type(name, (object,), {
            '__init__': init,
            '__slots__': tuple(slots),
            'astuple': astuple,
            '__str__': __str__,
            '__repr__': __repr__,
            '__eq__': __eq__,
        })
    
    
    Event = Struct('user', 'cmd', \
                   'arg1', 'arg2',  \
                   date=time.time, \
                   __name__='Event')
    
    aa = Event('pepe', 77)
    print(aa)
    raw = aa.astuple()
    
    bb = Event(*raw)
    print(bb)
    
    if aa == bb:
        print('Are equals')
    
    cc = Event(cmd='foo')
    print(cc)
    

    输出:

    <Event: user=pepe, cmd=77, arg1=None, arg2=None, date=1550051398.3651814>
    <Event: user=pepe, cmd=77, arg1=None, arg2=None, date=1550051398.3651814>
    Are equals
    <Event: user=None, cmd=foo, arg1=None, arg2=None, date=1550051403.7938335>
    
        17
  •  0
  •   Rob Lao    7 年前

    虽然有很多答案,但我找不到一个我满意的答案。我找到了自己的解决方案 property 为动态案例工作。回答原始问题的来源:

    #!/usr/local/bin/python3
    
    INITS = { 'ab': 100, 'cd': 200 }
    
    class DP(dict):
      def __init__(self):
        super().__init__()
        for k,v in INITS.items():
            self[k] = v 
    
    def _dict_set(dp, key, value):
      dp[key] = value
    
    for item in INITS.keys():
      setattr(
        DP,
        item,
        lambda key: property(
          lambda self: self[key], lambda self, value: _dict_set(self, key, value)
        )(item)
      )
    
    a = DP()
    print(a)  # {'ab': 100, 'cd': 200}
    a.ab = 'ab100'
    a.cd = False
    print(a.ab, a.cd) # ab100 False
    
        18
  •  -1
  •   M. Utku ALTINKAYA    16 年前

    动态附加属性的唯一方法是使用新属性创建一个新类及其实例。

    class Holder: p = property(lambda x: vs[i], self.fn_readonly)
    setattr(self, k, Holder().p)
    
        19
  •  -1
  •   teeks99    12 年前

    我最近遇到了一个类似的问题,我想出的解决方案 __getattr__ __setattr__ 对于我希望它处理的属性,其他一切都将传递给原始属性。

    class C(object):
        def __init__(self, properties):
            self.existing = "Still Here"
            self.properties = properties
    
        def __getattr__(self, name):
            if "properties" in self.__dict__ and name in self.properties:
                return self.properties[name] # Or call a function, etc
            return self.__dict__[name]
    
        def __setattr__(self, name, value):
            if "properties" in self.__dict__ and name in self.properties:
                self.properties[name] = value
            else:
                self.__dict__[name] = value
    
    if __name__ == "__main__":
        my_properties = {'a':1, 'b':2, 'c':3}
        c = C(my_properties)
        assert c.a == 1
        assert c.existing == "Still Here"
        c.b = 10
        assert c.properties['b'] == 10
    
        20
  •  -3
  •   Acecool    7 年前

    许多提供的答案要求每个属性有如此多的行,即/和/或-我会认为一个丑陋或冗长的实现,因为多个属性需要重复性,等等。我更喜欢将事物煮沸/简化,直到它们不能再简化,或者直到它不起多大作用为止。

    简而言之:在已完成的工作中,如果我重复两行代码,我通常会将其转换为单行助手函数,等等…我简化了数学或奇数参数,例如(start_x,start_y,end_x,end_y)到(x,y,w,h)ie x,y,x+w,y+h(有时需要min/max,或者如果w/h为负数,而实现不喜欢它,我将从x/y和abs w/h中减去。).

    重写内部getter/setter是一个不错的方法,但问题是您需要为每个类都这样做,或者将类作为父类设置为该基…这对我不起作用,因为我更愿意自由地选择继承的子/父节点、子节点等。

    我已经创建了一个解决方案,它在回答问题时不使用dict数据类型来提供数据,因为我发现输入数据很繁琐,等等……

    我的解决方案要求您在类的上方添加2行,为要添加属性的类创建一个基类,然后为每个类添加1行,您可以选择添加回调来控制数据,在数据更改时通知您,限制可以根据值和/或数据类型设置的数据,等等。

    您还可以选择使用_object.x、_object.x=value、_object.getx()、_object.setx(value),它们的处理方式相同。

    此外,这些值是唯一分配给类实例的非静态数据,但实际属性被分配给类,这意味着您不想重复、不需要重复的内容…您可以分配一个默认值,这样getter就不需要每次都分配它,尽管有一个选项可以覆盖默认值,还有一个选项可以通过覆盖默认值来返回原始存储值(注意:此方法意味着只有在分配了一个值时才分配原始值,否则它是无的-when重置该值,然后不分配任何值等。)

    也有许多助手函数-第一个被添加的属性向类中添加了2个左右的助手以引用实例值…它们是resetaccorpores(_key,..)varargs repeated(所有变量都可以使用第一个命名的args重复)和setaccessors(_key,_value),可以选择将更多的变量添加到主类中以帮助提高效率-计划的方法是:将访问器分组在一起的一种方法,因此,如果您倾向于一次重置几个访问器,则每次都可以将它们分配到一个组并重置该组,而不是f每次重复已命名的键,等等。

    实例/原始存储值存储在 班级。 第二类。引用为属性保存静态变量/值/函数的访问器类。级。是在设置/获取等过程中通过实例类访问时调用的属性本身。

    访问器类指向类,但由于它是内部的,所以需要在类中分配,这就是为什么我选择使用u name=accessorFunc(…)要分配它,每个属性一行,有许多可选参数可供使用(使用键控varargs是因为它们更容易、更高效地识别和维护)。

    如前所述,我还创建了许多函数,其中一些函数使用 访问器函数信息,因此不需要调用它(因为现在有点不方便-现在您需要使用_类)。 .functionname(_class_instance,args)-我使用堆栈/跟踪来获取实例引用以获取值,方法是添加运行此位马拉松的函数,或者向对象添加访问器并使用self(命名此函数以指出它们是针对实例的,并保留对self的访问权),accessorfunc类将引用以及函数定义中的其他信息)。

    还没有完全完成,但这是一个非常好的立足点。注意:如果不使用u name=accessorFunc(…)要创建属性,即使我在init函数中定义了该键,您也无法访问它。如果你这样做了,就没有问题了。

    另外:请注意,名称和密钥是不同的…名称是“正式”的,用于创建函数名,密钥用于数据存储和访问。ie _class.x,其中小写x是键,名称将为大写x,因此getx()是函数,而不是getx(),看起来有点奇怪。这允许self.x工作并看起来合适,但也允许getx()和look appropriate。

    我有一个示例类,其中的键/名称相同,并且要显示的是不同的。为了输出数据而创建的许多助手函数(注意:并非所有这些都是完整的),这样您就可以看到发生了什么。

    当前使用key:x、name:x输出的函数列表为:

    这绝不是一个全面的名单-有一些人在发帖的时候还没有写在上面…

    _instance.SetAccessors( _key, _value [ , _key, _value ] .. )                   Instance Class Helper Function: Allows assigning many keys / values on a single line - useful for initial setup, or to minimize lines.    In short: Calls this.Set<Name>( _value ) for each _key / _value pairing.
    _instance.ResetAccessors( _key [ , _key ] .. )                                 Instance Class Helper Function: Allows resetting many key stored values to None on a single line.                                           In short: Calls this.Reset<Name>() for each name provided.
    
    
    Note: Functions below may list self.Get / Set / Name( _args ) - self is meant as the class instance reference in the cases below - coded as this in AccessorFuncBase Class.
    
    this.GetX( _default_override = None, _ignore_defaults = False )                 GET:            Returns    IF ISSET: STORED_VALUE .. IF IGNORE_DEFAULTS: None  .. IF PROVIDED: DEFAULT_OVERRIDE ELSE: DEFAULT_VALUE       100
    this.GetXRaw( )                                                                 RAW:            Returns    STORED_VALUE                                                                                                     100
    this.IsXSet( )                                                                  ISSET:          Returns    ( STORED_VALUE != None )                                                                                         True
    
    this.GetXToString( )                                                            GETSTR:         Returns    str( GET )                                                                                                       100
    this.GetXLen( _default_override = None, _ignore_defaults = False )              LEN:            Returns    len( GET )                                                                                                       3
    this.GetXLenToString( _default_override = None, _ignore_defaults = False )      LENSTR:         Returns    str( len( GET ) )                                                                                                3
    this.GetXDefaultValue( )                                                        DEFAULT:        Returns    DEFAULT_VALUE                                                                                                    1111
    
    this.GetXAccessor( )                                                            ACCESSOR:       Returns    ACCESSOR_REF ( self.__<key> )                                                                                    [ AccessorFuncBase ] Key: x : Class ID: 2231452344344 : self ID: 2231448283848        Default: 1111       Allowed Types: {"<class 'int'>": "<class 'type'>", "<class 'float'>": "<class 'type'>"}     Allowed Values: None
    this.GetXAllowedTypes( )                                                        ALLOWED_TYPES:  Returns    Allowed Data-Types                                                                                               {"<class 'int'>": "<class 'type'>", "<class 'float'>": "<class 'type'>"}
    this.GetXAllowedValues( )                                                       ALLOWED_VALUES: Returns    Allowed Values                                                                                                   None
    
    this.GetXHelpers( )                                                             HELPERS:        Returns    Helper Functions String List - ie what you're reading now...                                                     THESE ROWS OF TEXT
    this.GetXKeyOutput( )                                                           Returns information about this Name / Key                                                                                                   ROWS OF TEXT
    this.GetXGetterOutput( )                                                        Returns information about this Name / Key                                                                                                   ROWS OF TEXT
    
    this.SetX( _value )                                                             SET:            STORED_VALUE Setter - ie Redirect to __<Key>.Set                                                                            N / A
    this.ResetX( )                                                                  RESET:          Resets STORED_VALUE to None                                                                                                 N / A
    
    this.HasXGetterPrefix( )                                                        Returns Whether or Not this key has a Getter Prefix...                                                                                      True
    this.GetXGetterPrefix( )                                                        Returns Getter Prefix...                                                                                                                    Get
    
    this.GetXName( )                                                                Returns Accessor Name - Typically Formal / Title-Case                                                                                       X
    this.GetXKey( )                                                                 Returns Accessor Property Key - Typically Lower-Case                                                                                        x
    this.GetXAccessorKey( )                                                         Returns Accessor Key - This is to access internal functions, and static data...                                                             __x
    this.GetXDataKey( )                                                             Returns Accessor Data-Storage Key - This is the location where the class instance value is stored..                                         _x
    

    正在输出的一些数据是:

    这是一个全新的类,使用demo类创建,除了名称(以便输出)之外,没有分配任何数据,它是foo,我使用的变量名…

    _foo         --- MyClass: ---- id( this.__class__ ): 2231452349064 :::: id( this ): 2231448475016
    
        Key       Getter Value        | Raw Key   Raw / Stored Value       | Get Default Value             Default Value            | Get Allowed Types             Allowed Types                                                              | Get Allowed Values            Allowed Values                                                                                                                                                                                                                   |
    
        Name:     _foo                | _Name:    _foo                     | __Name.DefaultValue( ):       AccessorFuncDemoClass    | __Name.GetAllowedTypes( )     <class 'str'>                                                              | __Name.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        x:        1111                | _x:       None                     | __x.DefaultValue( ):          1111                     | __x.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __x.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        y:        2222                | _y:       None                     | __y.DefaultValue( ):          2222                     | __y.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __y.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        z:        3333                | _z:       None                     | __z.DefaultValue( ):          3333                     | __z.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __z.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        Blah:     <class 'int'>       | _Blah:    None                     | __Blah.DefaultValue( ):       <class 'int'>            | __Blah.GetAllowedTypes( )     <class 'str'>                                                              | __Blah.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        Width:    1                   | _Width:   None                     | __Width.DefaultValue( ):      1                        | __Width.GetAllowedTypes( )    (<class 'int'>, <class 'bool'>)                                            | __Width.GetAllowedValues( )   Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        Height:   0                   | _Height:  None                     | __Height.DefaultValue( ):     0                        | __Height.GetAllowedTypes( )   <class 'int'>                                                              | __Height.GetAllowedValues( )  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |
        Depth:    2                   | _Depth:   None                     | __Depth.DefaultValue( ):      2                        | __Depth.GetAllowedTypes( )    Saved Value Restricted to Authorized Values ONLY                           | __Depth.GetAllowedValues( )   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |
    
    
    this.IsNameSet( ):    True      this.GetName( ):     _foo                     this.GetNameRaw( ):    _foo                     this.GetNameDefaultValue( ):    AccessorFuncDemoClass    this.GetNameLen( ):    4    this.HasNameGetterPrefix( ):    <class 'str'>                                this.GetNameGetterPrefix( ):    None
    this.IsXSet( ):       False     this.GetX( ):        1111                     this.GetXRaw( ):       None                     this.GetXDefaultValue( ):       1111                     this.GetXLen( ):       4    this.HasXGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetXGetterPrefix( ):       None
    this.IsYSet( ):       False     this.GetY( ):        2222                     this.GetYRaw( ):       None                     this.GetYDefaultValue( ):       2222                     this.GetYLen( ):       4    this.HasYGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetYGetterPrefix( ):       None
    this.IsZSet( ):       False     this.GetZ( ):        3333                     this.GetZRaw( ):       None                     this.GetZDefaultValue( ):       3333                     this.GetZLen( ):       4    this.HasZGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetZGetterPrefix( ):       None
    this.IsBlahSet( ):    False     this.GetBlah( ):     <class 'int'>            this.GetBlahRaw( ):    None                     this.GetBlahDefaultValue( ):    <class 'int'>            this.GetBlahLen( ):    13   this.HasBlahGetterPrefix( ):    <class 'str'>                                this.GetBlahGetterPrefix( ):    None
    this.IsWidthSet( ):   False     this.GetWidth( ):    1                        this.GetWidthRaw( ):   None                     this.GetWidthDefaultValue( ):   1                        this.GetWidthLen( ):   1    this.HasWidthGetterPrefix( ):   (<class 'int'>, <class 'bool'>)              this.GetWidthGetterPrefix( ):   None
    this.IsDepthSet( ):   False     this.GetDepth( ):    2                        this.GetDepthRaw( ):   None                     this.GetDepthDefaultValue( ):   2                        this.GetDepthLen( ):   1    this.HasDepthGetterPrefix( ):   None                                         this.GetDepthGetterPrefix( ):   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    this.IsHeightSet( ):  False     this.GetHeight( ):   0                        this.GetHeightRaw( ):  None                     this.GetHeightDefaultValue( ):  0                        this.GetHeightLen( ):  1    this.HasHeightGetterPrefix( ):  <class 'int'>                                this.GetHeightGetterPrefix( ):  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    

    这是在以相同的顺序分配所有foo属性(名称除外)之后:string,1.0,true,9,10,false

    this.IsNameSet( ):    True      this.GetName( ):     _foo                     this.GetNameRaw( ):    _foo                     this.GetNameDefaultValue( ):    AccessorFuncDemoClass    this.GetNameLen( ):    4    this.HasNameGetterPrefix( ):    <class 'str'>                                this.GetNameGetterPrefix( ):    None
    this.IsXSet( ):       True      this.GetX( ):        10                       this.GetXRaw( ):       10                       this.GetXDefaultValue( ):       1111                     this.GetXLen( ):       2    this.HasXGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetXGetterPrefix( ):       None
    this.IsYSet( ):       True      this.GetY( ):        10                       this.GetYRaw( ):       10                       this.GetYDefaultValue( ):       2222                     this.GetYLen( ):       2    this.HasYGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetYGetterPrefix( ):       None
    this.IsZSet( ):       True      this.GetZ( ):        10                       this.GetZRaw( ):       10                       this.GetZDefaultValue( ):       3333                     this.GetZLen( ):       2    this.HasZGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetZGetterPrefix( ):       None
    this.IsBlahSet( ):    True      this.GetBlah( ):     string Blah              this.GetBlahRaw( ):    string Blah              this.GetBlahDefaultValue( ):    <class 'int'>            this.GetBlahLen( ):    11   this.HasBlahGetterPrefix( ):    <class 'str'>                                this.GetBlahGetterPrefix( ):    None
    this.IsWidthSet( ):   True      this.GetWidth( ):    False                    this.GetWidthRaw( ):   False                    this.GetWidthDefaultValue( ):   1                        this.GetWidthLen( ):   5    this.HasWidthGetterPrefix( ):   (<class 'int'>, <class 'bool'>)              this.GetWidthGetterPrefix( ):   None
    this.IsDepthSet( ):   True      this.GetDepth( ):    9                        this.GetDepthRaw( ):   9                        this.GetDepthDefaultValue( ):   2                        this.GetDepthLen( ):   1    this.HasDepthGetterPrefix( ):   None                                         this.GetDepthGetterPrefix( ):   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    this.IsHeightSet( ):  True      this.GetHeight( ):   9                        this.GetHeightRaw( ):  9                        this.GetHeightDefaultValue( ):  0                        this.GetHeightLen( ):  1    this.HasHeightGetterPrefix( ):  <class 'int'>                                this.GetHeightGetterPrefix( ):  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    
    _foo         --- MyClass: ---- id( this.__class__ ): 2231452349064 :::: id( this ): 2231448475016
    
        Key       Getter Value        | Raw Key   Raw / Stored Value       | Get Default Value             Default Value            | Get Allowed Types             Allowed Types                                                              | Get Allowed Values            Allowed Values                                                                                                                                                                                                                   |
    
        Name:     _foo                | _Name:    _foo                     | __Name.DefaultValue( ):       AccessorFuncDemoClass    | __Name.GetAllowedTypes( )     <class 'str'>                                                              | __Name.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        x:        10                  | _x:       10                       | __x.DefaultValue( ):          1111                     | __x.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __x.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        y:        10                  | _y:       10                       | __y.DefaultValue( ):          2222                     | __y.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __y.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        z:        10                  | _z:       10                       | __z.DefaultValue( ):          3333                     | __z.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __z.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        Blah:     string Blah         | _Blah:    string Blah              | __Blah.DefaultValue( ):       <class 'int'>            | __Blah.GetAllowedTypes( )     <class 'str'>                                                              | __Blah.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        Width:    False               | _Width:   False                    | __Width.DefaultValue( ):      1                        | __Width.GetAllowedTypes( )    (<class 'int'>, <class 'bool'>)                                            | __Width.GetAllowedValues( )   Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
        Height:   9                   | _Height:  9                        | __Height.DefaultValue( ):     0                        | __Height.GetAllowedTypes( )   <class 'int'>                                                              | __Height.GetAllowedValues( )  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |
        Depth:    9                   | _Depth:   9                        | __Depth.DefaultValue( ):      2                        | __Depth.GetAllowedTypes( )    Saved Value Restricted to Authorized Values ONLY                           | __Depth.GetAllowedValues( )   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |
    

    请注意,由于受限制的数据类型或值限制,一些数据没有分配-这是由设计造成的。setter禁止分配错误的数据类型或值,甚至禁止将其指定为默认值(除非重写默认值保护行为)

    代码没有发布在这里,因为我在示例和解释之后没有空间…也因为它会改变。

    请注意:在这篇文章的时候,文件是混乱的-这将改变。但是,如果您以崇高的文本运行它并编译它,或者从python运行它,它将编译并吐出大量的信息-accessordb部分没有完成(它将用于更新print getter和getkeyoutput helper函数以及更改为一个实例函数,可能放在一个函数中并重命名-look f或者…

    下一步:并不是运行它所需要的所有东西——底部的很多注释内容是为了获得更多用于调试的信息——当您下载它时,它可能不在那里。如果是,您应该能够取消注释并重新编译以获取更多信息。

    我正在寻找一个需要我的类库的工作:通过,我的类(我的类库):…-如果你知道一个解决方案-发布它。

    课堂上唯一需要的就是台词- STR 用于调试 初始化 -它们可以从演示类中删除,但您需要注释掉或删除下面的一些行(foo/2/3)。

    上面的string、dict和util类是我的python库的一部分——它们并不完整。我从图书馆里复制了一些我需要的东西,并创造了一些新的东西。完整的代码将链接到完整的库,并包括它,同时提供更新的调用和删除代码(实际上,唯一剩下的代码将是demo类和print语句-accessorFunc系统将移动到库中)。

    文件的一部分:

    ##
    ## MyClass Test AccessorFunc Implementation for Dynamic 1-line Parameters
    ##
    class AccessorFuncDemoClassBase( ):
        pass
    class AccessorFuncDemoClass( AccessorFuncDemoClassBase ):
        __Name      = AccessorFuncBase( parent = AccessorFuncDemoClassBase, name = 'Name',      default = 'AccessorFuncDemoClass',  allowed_types = ( TYPE_STRING ),                    allowed_values = VALUE_ANY,                 documentation = 'Name Docs',        getter_prefix = 'Get',  key = 'Name',       allow_erroneous_default = False,    options = { } )
        __x         = AccessorFuncBase( parent = AccessorFuncDemoClassBase, name = 'X',         default = 1111,                     allowed_types = ( TYPE_INTEGER, TYPE_FLOAT ),       allowed_values = VALUE_ANY,                 documentation = 'X Docs',           getter_prefix = 'Get',  key = 'x',          allow_erroneous_default = False,    options = { } )
        __Height    = AccessorFuncBase( parent = AccessorFuncDemoClassBase, name = 'Height',    default = 0,                        allowed_types = TYPE_INTEGER,                       allowed_values = VALUE_SINGLE_DIGITS,       documentation = 'Height Docs',      getter_prefix = 'Get',  key = 'Height',     allow_erroneous_default = False,    options = { } )
    

    这种美使得使用accessorFuncs/callbacks/data-type/value-enforcement等动态添加属性创建新类变得非常容易。

    目前,链接位于(此链接应反映对文档的更改。): https://www.dropbox.com/s/6gzi44i7dh58v61/dynamic_properties_accessorfuncs_and_more.py?dl=0

    另外:如果您不使用高级文本,我建议您使用它而不是记事本++、Atom、可视代码和其他,因为正确的线程实现使它使用起来更快、更快……我也在为它开发一个类似于IDE的代码映射系统-看看: https://bitbucket.org/Acecool/acecoolcodemappingsystem/src/master/ (首先在包管理器中添加repo,然后安装plugin-当版本1.0.0准备就绪时,我会将其添加到主插件列表…)

    我希望这个解决方案有帮助…而且,一如既往:

    仅仅因为它起作用,就不能使它正确-乔希'阿齐科莫瑟