How to add property to a class dynamically?
目标是创建一个行为类似于db resultset的模拟类。
例如,如果使用dict表达式
1 2 | >>> dummy.ab 100 |
起初我想我可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
但
用
那么,在运行时创建实例属性的正确方法是什么?
P.S.我知道如何使用
我想我应该扩大这个答案,既然我年纪大了,聪明了,知道发生了什么事。迟到总比不迟到好。
可以将属性动态添加到类中。但这就是关键:你必须把它添加到类中。
1 2 3 4 5 6 7 8 | >>> class Foo(object): ... pass ... >>> foo = Foo() >>> foo.a = 3 >>> Foo.b = property(lambda self: self.a + 1) >>> foo.b 4 |
在上面的例子中,当我要求使用
描述符实际上是Python公开其整个OO实现的管道的方法。实际上,还有另一种类型的描述符比
1 2 3 4 5 6 7 8 | >>> 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> |
谦虚的方法只是另一种描述符。它的
1 2 | def __get__(self, instance, owner): return functools.partial(self.function, instance) |
不管怎样,我怀疑这就是为什么描述符只在类上工作的原因:它们首先是为类提供动力的东西的形式化。它们甚至是规则的例外:显然可以将描述符分配给类,而类本身就是EDOCX1的实例(25)!事实上,试图读取
我认为,几乎所有Python的OO系统都可以用Python表示,这很酷。:)
哦,如果你感兴趣的话,我写了一篇关于描述符的冗长的博客文章。
The goal is to create a mock class which behaves like a db resultset.
所以你想要的是一本字典,你可以把a['b']拼成a.b?
这很容易:
1 2 3 4 | class atdict(dict): __getattr__= dict.__getitem__ __setattr__= dict.__setitem__ __delattr__= dict.__delitem__ |
似乎您可以用
1 2 3 4 5 6 7 8 | from collections import namedtuple Foo = namedtuple('Foo', ['bar', 'quux']) foo = Foo(bar=13, quux=74) print foo.bar, foo.quux foo2 = Foo() # error |
如果您绝对需要编写自己的setter,则必须在类级别上执行元编程;
你不需要使用一个属性。只需重写
1 2 3 4 5 6 7 | 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。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | >>> 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! |
不能在运行时向实例添加新的
我在这个堆栈溢出帖子上问了一个类似的问题,创建了一个创建简单类型的类工厂。结果是这个答案有一个类工厂的工作版本。下面是一小段答案:
10您可以使用这个变量来创建默认值,这是您的目标(这个问题中还有一个解决这个问题的答案)。
How to add property to a python class dynamically?
假设您有一个要向其添加属性的对象。通常,我希望在需要开始管理对具有下游用法的代码中的属性的访问时使用属性,以便维护一致的API。现在,我通常会将它们添加到定义对象的源代码中,但假设您没有该访问权限,或者您需要真正以编程方式动态选择函数。
创建一个类使用基于
1 2 3 4 5 | class C(object): '''basic class''' _x = None o = C() |
在Python中,我们希望有一种明显的方式来做事情。但是,在本例中,我将展示两种方法:使用decorator符号,不使用decorator符号。首先,没有装饰符号。这对于getter、setter或deleter的动态分配可能更有用。
动态(即猴子修补)让我们为我们的班级创建一些:
1 2 3 4 5 6 7 8 | def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x |
现在我们把这些转让给地产。注意,我们可以在这里以编程方式选择函数,回答动态问题:
1 | C.x = property(getx, setx, delx,"I'm the 'x' property.") |
用途:
1 2 3 4 5 6 7 8 9 10 | >>> 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表示法那样做,但是在这种情况下,我们必须将所有方法命名为相同的名称(我建议将其保持与属性相同),因此编程分配不像使用上面的方法那样简单:
1 2 3 4 5 6 7 8 9 10 11 12 | @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分配给类:
1 | C.x = x |
用途:
1 2 3 4 5 6 7 8 9 10 11 12 | >>> 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 |
对于那些来自搜索引擎的用户,以下是我在谈论动态属性时所寻求的两个方面:
10如果您想要放置动态创建的属性,那么
如果只需要一个动态属性,请查看property()内置函数。
不确定我是否完全理解这个问题,但是您可以在运行时使用类的内置
1 2 3 4 5 6 7 8 9 10 | 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 |
又一个如何达到预期效果的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
现在我们可以做如下的事情:
1 2 3 4 5 6 | >>> foo = Foo('baz') >>> foo.baz = 5 >>> foo.bar 5 >>> foo.baz 5 |
最好的方法是定义
1 2 3 4 5 6 7 8 9 10 11 | 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 |
打印了
1 | c.ab = 33 |
这就产生了:
可以使用以下代码使用Dictionary对象更新类属性:
1 2 3 4 5 6 7 8 9 | 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 |
要回答问题的主要内容,您需要将dict中的只读属性作为不可变的数据源:
The goal is to create a mock class which behaves like a db resultset.
So for example, if a database query returns, using a dict expression,
{'ab':100, 'cd':200} , then I would to see
1
2 >>> dummy.ab
100
我将演示如何使用来自
1 2 3 4 5 6 7 8 9 10 11 | 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 |
返回
虽然有很多答案,但我找不到一个我满意的答案。我找到了自己的解决方案,使
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/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 |
这似乎可行(但见下文):
1 2 3 4 5 6 7 8 | 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__) |
如果您需要更复杂的行为,请随意编辑您的答案。
编辑对于大型数据集,以下内容可能更节省内存:
1 2 3 4 5 6 7 8 9 | 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__) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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 | >> 1 |
从KJFletch扩展理念
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | # 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) |
输出:
1 2 3 4 | <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> |
动态附加属性的唯一方法是使用新属性创建一个新类及其实例。
1 2 | class Holder: p = property(lambda x: vs[i], self.fn_readonly) setattr(self, k, Holder().p) |
我最近遇到了一个类似的问题,我提出的解决方案使用了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 |
许多提供的答案要求每个属性有如此多的行,即/和/或-我认为一个丑陋或冗长的实现,因为多个属性需要重复性,等等。我更喜欢将事情煮沸/简化,直到不能再简化它们,或者直到它不起多大作用为止。好的。
简而言之:在已完成的工作中,如果我重复两行代码,我通常会将其转换为单行助手函数,等等…我简化了数学或奇数参数,例如(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是因为它们更容易、更高效地识别和维护)。好的。
我还创建了许多函数,如前所述,其中一些函数使用访问器函数信息,因此不需要调用它(因为现在有点不方便-现在您需要使用_class..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输出的函数列表为:好的。
这绝不是一个全面的名单-有一些人在发帖的时候还没有写在上面…好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | _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,我使用的变量名…好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | _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好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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或者…好的。
下一步:并不是所有的东西都需要它来运行-底部的很多注释的东西是为了获得更多用于调试的信息-当你下载它时,它可能不在那里。如果是,您应该能够取消注释并重新编译以获取更多信息。好的。
我正在寻找一个需要我的类库的工作:通过,我的类(我的类库):…-如果你知道一个解决方案-发布它。好的。
类中唯一需要做的就是uuuuu行-str用于调试,init也是-它们可以从demo类中移除,但是您需要注释掉或移除下面的一些行(foo/2/3)。好的。
上面的string、dict和util类是我的python库的一部分,它们并不完整。我从图书馆里复制了一些我需要的东西,并创造了一些新的东西。完整的代码将链接到完整的库,并将其包括在内,同时提供更新的调用和删除代码(实际上,唯一剩下的代码将是demo类和print语句-accessorFunc系统将移动到库中)。好的。
文件的一部分:好的。
1 2 3 4 5 6 7 8 9 | ## ## 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://bitback.org/acecool/acecoolcodemappingsystem/src/master/(首先在包管理器中添加repo,然后安装plugin-当1.0.0版本准备好时,我会将其添加到主插件列表…)好的。
我希望这个解决方案有帮助…而且,一如既往:好的。
仅仅是因为它起作用了,并不能使它正确-乔希'阿齐柯尔'莫瑟好的。好啊。