很多提供的答案都要求每个属性有这么多行,例如/和/或-我认为是一个丑陋或乏味的实现,因为多个属性需要重复性,等等。我更喜欢不断地降低/简化它们,直到它们不能再被简化,或者直到它没有多大作用。
简而言之:在完成的工作中,如果我重复两行代码,我通常会将其转换为一个单行的helper函数,依此类推。。。我简化了一些数学或奇怪的参数,例如(start_x,start_y,end_x,end_y)到(x,y,w,h)即x,y,x+w,y+h(有时需要最小/最大值,或者如果w/h是负数并且实现不喜欢,我将从x/y和abs w/h中减去,等等).
重写内部getter/setter是一个不错的方法,但问题是您需要对每个类都这样做,或者将类父化到该基。。。这对我不起作用,因为我希望可以自由选择继承的子节点/父节点、子节点等。
我已经创建了一个解决方案,不使用Dict数据类型来提供数据,因为我发现输入数据是很繁琐的,等等。。。
我的解决方案要求您在类上方添加两行,以便为要向其添加属性的类创建基类,然后为每个类添加一行,并且您可以选择添加回调以控制数据、在数据更改时通知您、限制可基于值和/或数据类型设置的数据,等等。
您还可以选择使用_object.x、_object.x=value、_object.GetX()、_object.SetX(value),并且它们被等效地处理。
此外,这些值是唯一分配给类实例的非静态数据,但实际属性被分配给类,这意味着不想重复、不需要重复的事情。。。您可以分配一个默认值,这样getter每次都不需要它,尽管有一个选项可以覆盖默认值,还有另一个选项,这样getter通过覆盖默认值返回原始存储值(注意:这个方法意味着只有在分配值时才分配原始值,否则为“无”-当值重置时,则为“无”赋值
还有很多helper函数-第一个被添加的属性向类中添加了2个左右的helper,用于引用实例值。。。它们是重置访问器(_key,…)varargs repeated(都可以使用第一个命名的args重复)和SetAccessors(_key,_value),可以选择将更多的参数添加到主类中以提高效率-计划的方法是:将访问器分组在一起的方法,因此,如果您倾向于一次重置几个,每次,您可以将它们分配给一个组并重置该组,而不是每次重复指定的键,等等。
实例/原始存储值存储在
上课。
,那个班。引用包含属性的静态变量/值/函数的访问器类。_上课。是在设置/获取等过程中通过实例类访问时调用的属性本身。
访问器类指向该类,但因为它是内部的,所以需要在类中分配它,这就是为什么我选择使用'uuu Name=AccessorFunc(…)要分配它,每个属性有一行可使用的可选参数(使用键控varargs,因为它们更容易识别和维护,效率更高)。。。
我还创建了许多函数,如前所述,其中一些函数使用
访问器函数信息,因此不需要调用它(因为现在有点不方便-现在需要使用_类)。
.FunctionName(_class_instance,args)-我使用堆栈/跟踪来获取实例引用,通过添加运行此位马拉松的函数来获取值,或者通过将访问器添加到对象并使用self(将其命名为self)来获取值,AccessorFunc类引用,以及函数定义中的其他信息)。
虽然还没完成,但这是一个非常棒的支撑。注意:如果不使用u Name=AccessorFunc(…)要创建属性,即使我在init函数中定义了键,也不能访问它。如果你这样做了,那就没有问题了。
另外:请注意,名称和键是不同的。。。名称是“formal”,用于创建函数名,密钥用于数据存储和访问。ie _class.x其中小写x是键,名称将是大写x,因此GetX()是函数,而不是看起来有点奇怪的GetX()。这允许self.x工作并看起来合适,但也允许GetX()和看起来合适。
我设置了一个示例类,其中键/名称相同,但要显示的内容不同。为了输出数据而创建的许多helper函数(注意:并不是所有这些都是完整的),这样您就可以看到发生了什么。
使用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禁止分配错误的数据类型或值,甚至禁止将其分配为默认值(除非重写默认值保护行为)
代码还没有发布在这里,因为我没有空间后的例子和解释。。。也因为它会改变。
请注意:在发帖时,文件很乱-这将改变。但是,如果您在Sublime Text中运行它并编译它,或者从Python中运行它,它将编译并输出大量信息-AccessorDB部分没有完成(它将用于更新Print getter和GetKeyOutput helper函数,同时改为实例函数,可能放在一个函数中并重命名-查找它..)
下一步:并不是所有的东西都需要它来运行-底部的很多评论是为了获得更多用于调试的信息-当你下载它时,它可能不在那里。如果是,您应该能够取消注释并重新编译以获取更多信息。
我正在寻找一个需要MyClassBase的解决方案:pass,MyClass(MyClassBase):。。。-如果你知道一个解决方案-张贴它。
班上唯一需要的是线-
str公司
用于调试
初始
-它们可以从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/callbacks/data type/value-enforcement等动态添加的属性创建新类变得异常容易。
目前,链接位于(此链接应反映对文档的更改):
https://www.dropbox.com/s/6gzi44i7dh58v61/dynamic_properties_accessorfuncs_and_more.py?dl=0
另外:如果您不使用Sublime文本,我建议您不要使用Notepad++、Atom、可视化代码和其他代码,因为正确的线程实现使它使用起来更快。。。我也在为它开发一个类似IDE的代码映射系统-看看:
https://bitbucket.org/Acecool/acecoolcodemappingsystem/src/master/
(首先在包管理器中添加Repo,然后安装Plugin-当版本1.0.0准备好时,我将其添加到主插件列表中…)
我希望这个解决方案有助于。。。而且,一如既往:
只是因为它起作用,并不能使它正确-乔希'Acecool'莫斯