Rất nhiều câu trả lời được cung cấp yêu cầu rất nhiều dòng trên mỗi thuộc tính, tức là / và / hoặc - những gì tôi cho là việc triển khai xấu xí hoặc tẻ nhạt vì tính lặp đi lặp lại cần thiết cho nhiều thuộc tính, v.v. Tôi thích tiếp tục đun sôi / đơn giản hóa chúng cho đến khi chúng không thể được đơn giản hóa nữa hoặc cho đến khi nó không phục vụ nhiều mục đích để làm như vậy.
Tóm lại: trong các tác phẩm đã hoàn thành, nếu tôi lặp lại 2 dòng mã, tôi thường chuyển đổi nó thành một hàm trợ giúp dòng đơn, v.v ... Tôi đơn giản hóa toán học hoặc các đối số lẻ như (start_x, start_y, end_x, end_y) thành (x, y, w, h) tức là x, y, x + w, y + h (đôi khi yêu cầu min / max hoặc nếu w / h là âm và việc triển khai không giống như vậy, tôi sẽ trừ đi x / y và abs w / h. vv ..).
Ghi đè các getters / setters nội bộ là một cách tốt để đi, nhưng vấn đề là bạn cần phải làm điều đó cho mọi lớp, hoặc cha mẹ lớp đến cơ sở đó ... Điều này không phù hợp với tôi vì tôi thích tự do lựa chọn con cái / cha mẹ để thừa kế, nút con, v.v.
Tôi đã tạo ra một giải pháp trả lời câu hỏi mà không cần sử dụng kiểu dữ liệu Dict để cung cấp dữ liệu vì tôi thấy việc đó là tẻ nhạt để nhập dữ liệu, v.v ...
Giải pháp của tôi yêu cầu bạn thêm 2 dòng bên trên lớp để tạo lớp cơ sở cho lớp bạn muốn thêm thuộc tính, sau đó 1 dòng trên mỗi và bạn có tùy chọn thêm cuộc gọi lại để kiểm soát dữ liệu, thông báo cho bạn khi dữ liệu thay đổi , hạn chế dữ liệu có thể được đặt dựa trên giá trị và / hoặc loại dữ liệu và hơn thế nữa.
Bạn cũng có tùy chọn sử dụng _object.x, _object.x = value, _object.GetX (), _object.SetX (value) và chúng được xử lý tương đương.
Ngoài ra, các giá trị là dữ liệu không tĩnh duy nhất được gán cho thể hiện của lớp, nhưng thuộc tính thực tế được gán cho lớp có nghĩa là những điều bạn không muốn lặp lại, không cần phải lặp lại ... Bạn có thể gán một giá trị mặc định để getter không cần nó mỗi lần, mặc dù có một tùy chọn để ghi đè giá trị mặc định và có một tùy chọn khác để getter trả về giá trị được lưu trữ thô bằng cách ghi đè trả về mặc định (lưu ý: phương thức này có nghĩa là giá trị thô chỉ được gán khi giá trị được gán, nếu không thì là Không - khi giá trị được đặt lại, sau đó nó sẽ gán Không, v.v.)
Cũng có nhiều hàm trợ giúp - thuộc tính đầu tiên được thêm 2 hoặc nhiều trình trợ giúp vào lớp để tham chiếu các giá trị cá thể ... Chúng là các varargs ResetAccessors (_key, ..) ) và SetAccessors (_key, _value) với tùy chọn được thêm vào lớp chính để hỗ trợ hiệu quả - những cách được lên kế hoạch là: một cách để nhóm người truy cập cùng nhau, vì vậy, nếu bạn có xu hướng thiết lập lại một vài lần , bạn có thể gán chúng cho một nhóm và đặt lại nhóm thay vì lặp lại các khóa được đặt tên mỗi lần và hơn thế nữa.
Giá trị lưu trữ thể hiện / thô được lưu trữ tại lớp., lớp. tham chiếu Lớp Accessor chứa vars / value / hàm tĩnh cho thuộc tính. _lớp học. là chính thuộc tính được gọi khi được truy cập thông qua lớp cá thể trong khi thiết lập / nhận, v.v.
Accessor _ class .__ trỏ đến lớp, nhưng vì nó là nội bộ nên nó cần được gán trong lớp, đó là lý do tại sao tôi chọn sử dụng __Name = AccessorFunc (...) để gán nó, một dòng cho mỗi thuộc tính có nhiều tùy chọn sử dụng các đối số (sử dụng các vararg có khóa vì chúng dễ dàng và hiệu quả hơn để xác định và duy trì) ...
Tôi cũng tạo ra rất nhiều chức năng, như đã đề cập, một số trong số đó sử dụng thông tin chức năng của trình truy cập để không cần phải gọi (vì hiện tại nó hơi bất tiện - ngay bây giờ bạn cần sử dụng _ class. class .. , args) - Tôi đã sử dụng stack / dấu vết để lấy tham chiếu thể hiện để lấy giá trị bằng cách thêm các hàm chạy marathon bit này hoặc bằng cách thêm các hàm truy cập vào đối tượng và sử dụng chính nó (đặt tên này để chỉ ra chúng ví dụ và để giữ quyền truy cập vào bản thân, tham chiếu lớp AccessorFunc và các thông tin khác từ bên trong các định nghĩa hàm).
Nó không hoàn thành, nhưng nó là một chân giữ tuyệt vời. Lưu ý: Nếu bạn không sử dụng __Name = AccessorFunc (...) để tạo các thuộc tính, bạn sẽ không có quyền truy cập vào phím __ ngay cả khi tôi xác định nó trong hàm init. Nếu bạn làm, sau đó không có vấn đề.
Ngoài ra: Lưu ý rằng Tên và Khóa khác nhau ... Tên là 'chính thức', được sử dụng trong Tạo tên hàm và khóa dành cho lưu trữ và truy cập dữ liệu. tức là _group.x trong đó chữ thường x là khóa, tên sẽ là chữ hoa X sao cho GetX () là hàm thay vì Getx () trông hơi kỳ lạ. điều này cho phép self.x hoạt động và trông phù hợp, nhưng cũng cho phép GetX () và trông phù hợp.
Tôi có một lớp ví dụ được thiết lập với khóa / tên giống hệt nhau và khác nhau để hiển thị. rất nhiều hàm trợ giúp được tạo để xuất dữ liệu (Lưu ý: Không phải tất cả các chức năng này đã hoàn tất) để bạn có thể thấy những gì đang diễn ra.
Danh sách các hàm hiện tại sử dụng khóa: x, name: X xuất ra dưới dạng:
Đây không phải là một danh sách toàn diện - có một vài cái chưa được đưa vào danh sách này tại thời điểm đăng ...
_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
Một số dữ liệu được xuất ra là:
Đây là một lớp hoàn toàn mới được tạo bằng lớp Demo mà không có bất kỳ dữ liệu nào được gán ngoài tên (vì vậy nó có thể là đầu ra) là _foo, tên biến tôi đã sử dụng ...
_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)
Và đây là sau khi gán tất cả các thuộc tính _foo (trừ tên) các giá trị sau theo cùng một thứ tự: 'chuỗi', 1.0, True, 9, 10, Sai
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) |
Lưu ý rằng do các loại dữ liệu bị hạn chế hoặc hạn chế giá trị, một số dữ liệu không được chỉ định - đây là do thiết kế. Trình thiết lập cấm các kiểu dữ liệu hoặc giá trị xấu được gán, thậm chí không được gán làm giá trị mặc định (trừ khi bạn ghi đè hành vi bảo vệ giá trị mặc định)
Mã chưa được đăng ở đây vì tôi không có chỗ sau các ví dụ và giải thích ... Cũng bởi vì nó sẽ thay đổi.
Xin lưu ý: tại thời điểm đăng bài này, tệp bị lộn xộn - điều này sẽ thay đổi. Nhưng, nếu bạn chạy nó trong Sublime Text và biên dịch nó, hoặc chạy nó từ Python, nó sẽ biên dịch và phun ra một tấn thông tin - phần AccessorDB không được thực hiện (sẽ được sử dụng để cập nhật Trình trợ giúp Print Getters và GetKeyOutput các chức năng cùng với việc được thay đổi thành một chức năng Instance, có thể được đưa vào một chức năng duy nhất và được đổi tên - hãy tìm nó ..)
Tiếp theo: Không phải mọi thứ đều cần thiết để nó chạy - rất nhiều nội dung được nhận xét ở phía dưới là để biết thêm thông tin được sử dụng để gỡ lỗi - nó có thể không ở đó khi bạn tải xuống. Nếu có, bạn sẽ có thể bỏ ghi chú và biên dịch lại để có thêm thông tin.
Tôi đang tìm kiếm một giải pháp cần MyClassBase: pass, MyClass (MyClassBase): ... - nếu bạn biết về một giải pháp - hãy đăng nó.
Điều duy nhất cần thiết trong lớp là các dòng __ - str là để gỡ lỗi như là init - chúng có thể bị xóa khỏi Lớp Demo nhưng bạn sẽ cần nhận xét hoặc xóa một số dòng bên dưới (_foo / 2/3 ) ..
Các lớp String, Dict và Util ở trên cùng là một phần của thư viện Python của tôi - chúng chưa hoàn thành. Tôi đã sao chép một vài thứ tôi cần từ thư viện và tôi đã tạo ra một vài thứ mới. Mã đầy đủ sẽ liên kết đến thư viện hoàn chỉnh và sẽ bao gồm nó cùng với việc cung cấp các cuộc gọi được cập nhật và xóa mã (thực tế, mã duy nhất còn lại sẽ là Lớp Demo và các câu lệnh in - hệ thống AccessorFunc sẽ được chuyển đến thư viện). ..
Một phần của tập tin:
##
## 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 = { } )
Vẻ đẹp này giúp dễ dàng tạo các lớp mới với các thuộc tính được thêm động với AccessorFuncs / callbacks / data-type / value, v.v.
Hiện tại, liên kết đang ở (Liên kết này sẽ phản ánh các thay đổi đối với tài liệu.): Https://www.dropbox.com/s/6gzi44i7dh58v61/dynamic_properies_accessorfuncs_and_more Hebdl=0
Ngoài ra: Nếu bạn không sử dụng Sublime Text, tôi khuyên dùng nó trên Notepad ++, Atom, Visual Code và các loại khác vì việc triển khai luồng phù hợp làm cho nó sử dụng nhanh hơn nhiều, nhanh hơn ... Tôi cũng đang làm việc trên một mã giống như IDE hệ thống ánh xạ cho nó - hãy xem: https://bitbucket.org/Acecool/acecoolcodemappingsystem/src/master/ (Trước tiên hãy thêm Repo trong Trình quản lý gói, sau đó Cài đặt Plugin - khi phiên bản 1.0.0 đã sẵn sàng, tôi sẽ thêm nó vào danh sách plugin chính ...)
Tôi hy vọng giải pháp này sẽ giúp ... và, như mọi khi:
Chỉ vì nó hoạt động, không làm cho nó đúng - Josh 'Acecool' Moser
:
và các__init__
tham chiếuself.fn_readyonly
.