问题:如何动态地向类添加属性?
目标是创建一个行为类似db结果集的模拟类。
因此,例如,如果数据库查询使用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])
根本没有用。
那么在运行时创建实例属性的正确方法是什么?
回答 0
我想我应该扩大这个答案,因为我年龄较大,比较聪明,并且知道发生了什么事。迟到总比不到好。
您可以动态地向类添加属性。但这很重要:您必须将其添加到类中。
>>> class Foo(object):
... pass
...
>>> foo = Foo()
>>> foo.a = 3
>>> Foo.b = property(lambda self: self.a + 1)
>>> foo.b
4
property
实际上,A 是称为描述符的事物的简单实现。该对象为给定类的给定属性提供自定义处理。Kinda就像一种从if
树上拔出一棵大树的方法__getattribute__
。
当我要求foo.b
在上面的例子中,Python看到的是,b
在类实现限定的描述符协议哪位只是意味着它是一个对象__get__
,__set__
或__delete__
方法。描述符声明负责处理该属性,因此Python调用Foo.b.__get__(foo, Foo)
,并将返回值作为属性值传递回给您。在的情况下property
,每一种方法只是调用fget
,fset
或fdel
你传递给property
构造函数。
描述符实际上是Python公开其整个OO实现的基本方法。实际上,还有一种比更为常见的描述符property
。
>>> 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>
谦虚方法只是另一种描述符。它__get__
以调用实例为第一个参数;实际上,它是这样做的:
def __get__(self, instance, owner):
return functools.partial(self.function, instance)
无论如何,我怀疑这就是为什么描述符仅在类上起作用的原因:它们是首先为类提供支持的东西的形式化形式。它们甚至是规则的exceptions:您显然可以为一个类分配描述符,而类本身就是type
!的实例。实际上,试图读取Foo.b
静态调用property.__get__
;当描述符作为类属性访问时,返回它们自己只是惯用的。
我认为几乎所有Python的OO系统都可以用Python表示非常酷。:)
回答 1
目标是创建一个行为类似db结果集的模拟类。
因此,您需要一本可以将a [‘b’]拼写为ab的字典吗?
这很简单:
class atdict(dict):
__getattr__= dict.__getitem__
__setattr__= dict.__setitem__
__delattr__= dict.__delitem__
回答 2
似乎您可以使用来更简单地解决此问题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()
在实例上不起作用。
回答 3
您不需要为此使用属性。只需重写__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!")
多田
>>> 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!
回答 4
如何动态地向python类添加属性?
假设您有一个对象要添加属性。通常,当我需要开始管理对具有下游用法的代码中的属性的访问时,我想使用属性,以便可以维护一致的API。现在,我通常将它们添加到定义对象的源代码中,但是让我们假设您没有该访问权限,或者您需要以编程方式真正地动态选择函数。
建立类
使用基于的文档property
的示例,让我们创建一个具有“隐藏”属性的对象类并创建一个实例:
class C(object):
'''basic class'''
_x = None
o = C()
在Python中,我们期望有一种显而易见的处理方式。但是,在这种情况下,我将展示两种方式:使用装饰符表示法和不使用装饰符表示法。首先,没有装饰符号。这对于动态获取,设置或删除程序可能更为有用。
动态(又名Monkey修补)
让我们为我们的Class创建一些:
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.
装饰工
我们可以使用装饰器符号做与上面相同的操作,但是在这种情况下,我们必须将所有方法都命名为相同的名称(我建议将其与属性保持相同),因此,程序化赋值并不是那么简单它使用上面的方法:
@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
并将属性对象及其提供的设置器和删除器分配给该类:
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
回答 5
我在这个Stack Overflow帖子上问了一个相似的问题,以创建一个创建简单类型的类工厂。结果是这个答案具有Class工厂的工作版本。这是答案的片段:
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
不知道我是否完全理解这个问题,但是您可以在运行时使用类的内置实例属性进行修改__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
回答 7
对于那些来自搜索引擎的人来说,这是我在谈论动态属性时正在寻找的两件事:
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__
仅在需要该值时才做某事是很好的,例如查询数据库。设置/获取组合可以简化对类中存储的数据的访问(就像上面的示例一样)。
如果只需要一个动态属性,请查看property()内置函数。
回答 8
您不能property()
在运行时向实例添加新实例,因为属性是数据描述符。相反,您必须动态创建一个新类或重载__getattribute__
以处理实例上的数据描述符。
回答 9
最好的方法是通过定义__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'
回答 10
另一个例子,如何达到预期的效果
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
回答 11
这是一个解决方案:
- 允许将属性名称指定为string,因此它们可以来自某些外部数据源,而不是在程序中列出的所有名称。
- 在定义类时添加属性,而不是在每次创建对象时添加属性。
定义了类之后,只需执行以下操作即可向其动态添加属性:
setattr(SomeClass, 'propertyName', property(getter, setter))
这是一个经过Python 3测试的完整示例:
#!/usr/bin/env python3
class Foo():
pass
def get_x(self):
return 3
def set_x(self, value):
print("set x on %s to %d" % (self, value))
setattr(Foo, 'x', property(get_x, set_x))
foo1 = Foo()
foo1.x = 12
print(foo1.x)
回答 12
您可以使用以下代码通过字典对象更新类属性:
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
回答 13
这与OP想要的有所不同,但是我动了动脑筋,直到找到可行的解决方案为止,所以我在这里为下一个家伙/女友
我需要一种方法来指定动态的setter和getter。
class X:
def __init__(self, a=0, b=0, c=0):
self.a = a
self.b = b
self.c = c
@classmethod
def _make_properties(cls, field_name, inc):
_inc = inc
def _get_properties(self):
if not hasattr(self, '_%s_inc' % field_name):
setattr(self, '_%s_inc' % field_name, _inc)
inc = _inc
else:
inc = getattr(self, '_%s_inc' % field_name)
return getattr(self, field_name) + inc
def _set_properties(self, value):
setattr(self, '_%s_inc' % field_name, value)
return property(_get_properties, _set_properties)
我提前知道我的领域,所以我要创建我的属性。注意:您不能执行此PER实例,这些属性将存在于类中!!!
for inc, field in enumerate(['a', 'b', 'c']):
setattr(X, '%s_summed' % field, X._make_properties(field, inc))
让我们现在测试一下。
x = X()
assert x.a == 0
assert x.b == 0
assert x.c == 0
assert x.a_summed == 0 # enumerate() set inc to 0 + 0 = 0
assert x.b_summed == 1 # enumerate() set inc to 1 + 0 = 1
assert x.c_summed == 2 # enumerate() set inc to 2 + 0 = 2
# we set the variables to something
x.a = 1
x.b = 2
x.c = 3
assert x.a_summed == 1 # enumerate() set inc to 0 + 1 = 1
assert x.b_summed == 3 # enumerate() set inc to 1 + 2 = 3
assert x.c_summed == 5 # enumerate() set inc to 2 + 3 = 5
# we're changing the inc now
x.a_summed = 1
x.b_summed = 3
x.c_summed = 5
assert x.a_summed == 2 # we set inc to 1 + the property was 1 = 2
assert x.b_summed == 5 # we set inc to 3 + the property was 2 = 5
assert x.c_summed == 8 # we set inc to 5 + the property was 3 = 8
令人困惑吗?是的,很抱歉,我无法提出任何有意义的现实示例。同样,这也不适合那些轻松的人。
回答 14
这似乎可行(但请参见下文):
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__)
回答 15
为了回答问题的主旨,您希望将字典中的只读属性作为不可变数据源:
目标是创建一个行为类似db结果集的模拟类。
因此,例如,如果数据库查询使用dict表达式返回
{'ab':100, 'cd':200}
,那么我将看到>>> dummy.ab 100
我将演示如何使用namedtuple
来自collections
模块的a来完成此任务:
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
回答 16
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
回答 17
从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>
回答 18
尽管给出了很多答案,但我找不到我满意的答案。我想出了自己的解决方案,该解决方案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
回答 19
对我有用的是这样的:
class C:
def __init__(self):
self._x=None
def g(self):
return self._x
def s(self, x):
self._x = x
def d(self):
del self._x
def s2(self,x):
self._x=x+x
x=property(g,s,d)
c = C()
c.x="a"
print(c.x)
C.x=property(C.g, C.s2)
C.x=C.x.deleter(C.d)
c2 = C()
c2.x="a"
print(c2.x)
输出量
a
aa
回答 20
最近,我遇到了一个类似的问题,即我想出的解决方案使用了它,__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
回答 21
这是通过编程创建属性对象的简单示例。
#!/usr/bin/python3
class Counter:
def __init__(self):
cls = self.__class__
self._count = 0
cls.count = self.count_ref()
def count_get(self):
print(f'count_get: {self._count}')
return self._count
def count_set(self, value):
self._count = value
print(f'count_set: {self._count}')
def count_del(self):
print(f'count_del: {self._count}')
def count_ref(self):
cls = self.__class__
return property(fget=cls.count_get, fset=cls.count_set, fdel=cls.count_del)
counter = Counter()
counter.count
for i in range(5):
counter.count = i
del counter.count
'''
output
======
count_get: 0
count_set: 0
count_set: 1
count_set: 2
count_set: 3
count_set: 4
count_del: 4
'''
回答 22
动态附加属性的唯一方法是使用新属性创建一个新类及其实例。
class Holder: p = property(lambda x: vs[i], self.fn_readonly)
setattr(self, k, Holder().p)
回答 23
提供的很多答案每个属性需要这么多行,即/和/或-由于多个属性需要重复性,我认为这是丑陋或乏味的实现。不能再简化了,或者直到它没有太大用处为止。
简而言之:在完成的作品中,如果我重复两行代码,通常会将其转换为单行辅助函数,以此类推…将数学或奇数参数(例如(start_x,start_y,end_x,end_y)简化为(x,y,w,h)即x,y,x + w,y + h(有时需要min / max或如果w / h为负且实现不喜欢它,我将从x /中减去y和ab w / h等。)。
重写内部getter / setter方法是可行的方法,但是问题是您需要为每个类都这样做,或者将该类作为该基础的父类…这对我不起作用,因为我更希望成为自由选择子代/父代进行继承,子节点等。
我创建了一个解决方案,无需使用Dict数据类型来提供数据即可回答问题,因为我发现输入数据等操作很繁琐,等等。
我的解决方案要求您在类上方添加2行,以为要向其添加属性的类创建基类,然后为每个类添加1行,并且您可以选择添加回调以控制数据,并在数据更改时通知您,限制可以根据值和/或数据类型等进行设置的数据。
您还可以选择使用_object.x,_object.x =值,_object.GetX(),_object.SetX(值),并且它们被等效地处理。
此外,值是分配给类实例的唯一非静态数据,但是实际属性却分配给了类,这意味着您不想重复的事情,不需要重复…可以分配一个默认值,因此每次都有一个不需要的getter,尽管有一个选项可以覆盖默认的默认值,还有另一个选项可以使getter通过覆盖默认的返回值来返回原始存储值(注意:此方法表示仅在分配值时才分配原始值,否则为None-当值重置时,它分配None等。)
辅助函数也有很多-添加的第一个属性将2个左右的辅助函数添加到类中以引用实例值…它们是ResetAccessors(_key,..)varargs重复(所有操作都可以使用第一个命名的args重复进行) )和SetAccessors(_key,_value),还可以选择将更多选项添加到主类中以提高效率-计划的方法是:一种将访问器组合在一起的方式,因此,如果您倾向于每次都重置一些访问器,您可以将它们分配给一个组并重置该组,而不必每次都重复命名的密钥,甚至更多。
实例/原始存储值存储在类中。, 班上。引用访问器类,该类保存该属性的静态vars / values / functions。_类。是属性本身,在设置/获取等过程中通过实例类访问时会调用该属性。
访问器_class .__指向该类,但是由于它是内部的,因此需要在该类中进行分配,这就是为什么我选择使用__Name = AccessorFunc(…)对其进行分配的原因,每个属性一行包含多个可选项要使用的参数(使用键控varargs,是因为它们更容易,更有效地标识和维护)…
如前所述,我还创建了许多函数,其中一些函数使用访问器函数信息,因此不需要调用(因为目前有点不方便-现在您需要使用 _class。.FunctionName(_class_instance ,args)-通过添加运行此马拉松马拉松函数或将访问器添加到对象并使用self(命名为指出它们的方法),我可以使用堆栈/跟踪来获取实例引用以获取值是针对实例的,并保留对自身,AccessorFunc类引用以及函数定义内的其他信息的访问)。
尚未完成,但这是一个了不起的立足点。注意:如果不使用__Name = AccessorFunc(…)创建属性,则即使我在init函数中定义了__键,也无法访问__键。如果这样做,则没有问题。
另外:请注意,名称和键是不同的…名称是“正式的”,在函数名称创建中使用,并且键用于数据存储和访问。即_class.x,其中小写的x是键,名称将是大写的X,因此GetX()是函数,而不是看起来有些奇怪的Getx()。这可以使self.x正常工作并看起来合适,但也可以使GetX()看起来合适。
我有一个示例类,其键/名称相同,但显示不同。为了输出数据而创建了许多辅助函数(注意:并非所有这些都是完整的),因此您可以看到发生了什么。
使用键:x,名称: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) |
请注意,由于数据类型或值的限制,未分配某些数据-这是设计使然。设置器禁止分配错误的数据类型或值,甚至禁止将其分配为默认值(除非您覆盖默认值保护行为)
该代码尚未发布在这里,因为在示例和说明之后我没有足够的空间…也是因为它将更改。
请注意:在发布时,文件杂乱无章-这将改变。但是,如果您在Sublime Text中运行它并进行编译,或者从Python运行它,它将编译并吐出大量信息-AccessorDB部分未完成(将用于更新Print Getters和GetKeyOutput帮助器)函数以及被更改为Instance函数,可能放在一个函数中并重命名-查找它。
下一步:运行它并不需要所有内容-底部的很多注释内容是用于调试的更多信息-下载时可能不存在。如果是这样,您应该可以取消注释并重新编译以获得更多信息。
我正在寻找一种解决方案,需要MyClassBase:通过,MyClass(MyClassBase):…-如果您知道解决方案,请发布它。
该类中唯一需要的是__行-str和init一样都是用于调试的-可以将它们从Demo类中删除,但是您需要注释掉或删除下面的一些行(_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 /回调/数据类型/值强制等动态添加属性来创建新类变得异常容易。
目前,链接位于(此链接应反映对文档的更改。):https : //www.dropbox.com/s/6gzi44i7dh58v61/dynamic_properties_accessorfuncs_and_more.py?dl=0
另外:如果您不使用Sublime Text,我建议在Notepad ++,Atom,Visual Code和其他语言上使用它,因为适当的线程实现使其使用起来非常快得多…我也在研究类似IDE的代码映射系统-请看一下:https : //bitbucket.org/Acecool/acecoolcodemappingsystem/src/master/(首先在软件包管理器中添加Repo,然后再安装插件-在1.0.0版本准备就绪时,我将添加它到主插件列表…)
我希望这个解决方案能对您有所帮助……并且一如既往:
仅仅因为它有效,就不能使它正确-Josh’Acecool’Moser