许多提供的答案需要每个属性这么多行,即 / 和 / 或 - 由于多个属性需要重复性等,我认为这是一个丑陋或乏味的实现。我更喜欢保持精简/简化它们直到它们不能再简化,或者直到它没有太多的目的。
简而言之:在已完成的作品中,如果我重复 2 行代码,我通常会将其转换为单行辅助函数,依此类推……我将数学或奇数参数(例如(start_x、start_y、end_x、end_y))简化为( x, y, w, h ) 即 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 每次都不需要它,尽管有一个选项可以覆盖默认默认值,还有另一个选项是 getter 通过覆盖默认返回值返回原始存储值(注意:此方法表示仅在分配值时分配原始值,否则为 None - 当值为 Reset 时,则分配 None 等。)
也有许多辅助函数 - 添加的第一个属性向类添加 2 个左右的辅助函数以引用实例值...它们是 ResetAccessors(_key, ..) 可变参数重复(所有都可以使用第一个命名参数重复) 和 SetAccessors( _key, _value ) 可以选择在主类中添加更多以帮助提高效率 - 计划的方法是:一种将访问器组合在一起的方法,因此如果您倾向于一次重置几个访问器,则每次,您可以将它们分配给一个组并重置该组,而不是每次都重复命名键等等。
实例/原始存储值存储在类中。, 班上。引用包含属性的静态变量/值/函数的访问器类。_班级。是在设置/获取等期间通过实例类访问时调用的属性本身。
Accessor _class.__ 指向该类,但由于它是内部的,因此需要在类中分配,这就是为什么我选择使用 __Name = AccessorFunc( ... ) 来分配它,每个属性一行有许多可选要使用的参数(使用键控可变参数,因为它们更容易识别和维护)......
如前所述,我还创建了很多函数,其中一些使用访问器函数信息,因此不需要调用它(因为目前有点不方便 - 现在您需要使用_class..FunctionName( _class_instance , args ) - 我使用堆栈/跟踪来获取实例引用以获取值,方法是添加运行此位马拉松的函数,或者通过将访问器添加到对象并使用 self (命名为指出它们'用于实例并保留对 self、AccessorFunc 类引用和函数定义中的其他信息的访问)。
它还没有完成,但它是一个很棒的立足点。注意:如果您不使用 __Name = AccessorFunc( ... ) 创建属性,您将无法访问 __ 键,即使我在 init 函数中定义了它。如果你这样做了,那么就没有问题了。
另外:注意名称和键是不同的...名称是“正式的”,用于函数名称创建,键用于数据存储和访问。即 _class.x 其中小写 x 是键,名称将是大写 X,因此 GetX() 是函数,而不是看起来有点奇怪的 Getx()。这允许 self.x 工作并且看起来合适,但也允许 GetX( ) 并且看起来合适。
我有一个示例类,其键/名称相同,但显示不同。为了输出数据而创建了许多辅助函数(注意:并非所有这些都是完整的),因此您可以看到发生了什么。
当前使用 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 属性(除了 name )以下值之后:'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 Getters 和 GetKeyOutput 帮助器函数以及被更改为实例函数,可能放入单个函数并重命名 - 寻找它..)
下一篇:运行它并不是所有的东西都需要——底部的许多注释内容是为了提供更多用于调试的信息——下载它时它可能不存在。如果是,您应该能够取消注释并重新编译以获取更多信息。
我正在寻找需要 MyClassBase: pass, MyClass( MyClassBase ): ... - 如果您知道解决方案 - 发布它。
类中唯一需要的是 __ 行 - str和init一样用于调试- 它们可以从演示类中删除,但您需要注释掉或删除下面的一些行( _foo / 2 / 3 )..
顶部的 String、Dict 和 Util 类是我的 Python 库的一部分——它们并不完整。我从图书馆复制了一些我需要的东西,并创建了一些新的东西。完整的代码将链接到完整的库,并将包含它以及提供更新的调用和删除代码(实际上,剩下的唯一代码将是演示类和打印语句 - 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