很多提供的答案需要这么多行每个属性,即/和/或-我认为一个丑陋或乏味的实现,因为多个属性需要重复,等等。我更喜欢把事情简化,直到它们不能再简化,或者直到这样做没有多大意义为止。
简而言之:在完成的作品中,如果我重复2行代码,我通常会将其转换为单行helper函数,等等……我简化了数学或奇怪的参数,如(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 / setters是一个不错的方法,但问题是你需要对每个类都这样做,或者将类父化到那个基…这对我来说并不适用,因为我更喜欢自由地选择继承的子/父节点,子节点等。
我已经创建了一个解决方案,回答了这个问题,而不使用Dict数据类型来提供数据,因为我发现输入数据很乏味,等等…
我的解决方案需要你在你的类上面添加2行额外的代码,为你想要添加属性的类创建一个基类,然后每一行,你可以选择添加回调来控制数据,当数据发生变化时通知你,限制可以基于值和/或数据类型设置的数据,等等。
您还可以选择使用_object。x, _object。X = value, _object。GetX(), _object。SetX(value),它们被等效地处理。
Additionally, the values are the only non-static data which are assigned to the class instance, but the actual property is assigned to the class meaning the things you don't want to repeat, don't need to be repeated... You can assign a default value so the getter doesn't need it each time, although there is an option to override the default default value, and there is another option so the getter returns the raw stored value by overriding default returns ( note: this method means the raw value is only assigned when a value is assigned, otherwise it is None - when the value is Reset, then it assigns None, etc.. )
There are many helper functions too - the first property which gets added adds 2 or so helpers to the class for referencing the instance values... They are ResetAccessors( _key, .. ) varargs repeated ( all can be repeated using the first named args ) and SetAccessors( _key, _value ) with the option of more being added to the main class to aide in efficiency - the ones planned are: a way to group accessors together, so if you tend to reset a few at a time, every time, you can assign them to a group and reset the group instead of repeating the named keys each time, and more.
实例/原始存储值存储在类中。, __类。引用访问器类,该类保存属性的静态变量/值/函数。_class。属性本身,在设置/获取等过程中通过实例类访问时被调用。
Accessor _class。__指向类,但因为它是内部的,所以需要在类中赋值,这就是为什么我选择使用__Name = AccessorFunc(…)要为它赋值,每个属性一行,并使用许多可选参数(使用键控可变参数,因为它们更容易识别和维护)…
I also create a lot of functions, as mentioned, some of which use accessor function information so it doesn't need to be called ( as it is a bit inconvenient at the moment - right now you need to use _class..FunctionName( _class_instance, args ) - I got around using the stack / trace to grab the instance reference to grab the value by adding the functions which either run this bit marathon, or by adding the accessors to the object and using self ( named this to point out they're for the instance and to retain access to self, the AccessorFunc class reference, and other information from within the function definitions ).
它还没有完全完成,但它是一个很好的立足点。注意:如果你不使用__Name = AccessorFunc(…)要创建属性,你将无法访问__键,即使我在init函数中定义了它。如果你这样做了,那么就没有问题。
另外:注意Name和Key是不同的…名称为“正式”,用于函数名称创建,键用于数据存储和访问。ie _class。其中小写x是键,名称将是大写x,因此GetX()是函数而不是GetX(),这看起来有点奇怪。这允许self。x工作和看起来合适,但也允许GetX()和看起来合适。
我有一个例子类设置键/名称相同,不同的显示。为了输出数据而创建了许多helper函数(注意:不是所有这些都是完整的),所以你可以看到正在发生什么。
使用键: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) |
注意,由于数据类型或值的限制,一些数据没有被分配——这是有意为之。setter禁止分配错误的数据类型或值,甚至禁止将其分配为默认值(除非覆盖默认值保护行为)
代码没有发布在这里,因为在示例和解释之后我没有空间了……也因为它会改变。
请注意:在这个发布的时候,文件是混乱的-这将会改变。但是,如果你在Sublime Text中运行它并编译它,或者从Python中运行它,它将编译并输出大量信息- AccessorDB部分还没有完成(将用于更新Print getter和GetKeyOutput helper函数,同时被更改为一个实例函数,可能放入一个单独的函数并重命名-寻找它..)
其次:并不是运行它所需要的所有东西——底部的许多注释是用于调试的更多信息——当你下载它时,它可能不存在。如果是,您应该能够取消注释并重新编译以获得更多信息。
我正在寻找一个工作区,需要MyClassBase:通过,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