تنفيذ واصفات الفئة عن طريق تصنيف فئة 'النوع'
-
17-09-2020 - |
سؤال
أود الحصول على بعض واصفات البيانات كجزء من الفصل.بمعنى أنني أرغب في أن تكون سمات الفصل في الواقع خصائص ، يتم التعامل مع الوصول إليها بواسطة طرق الفصل.
يبدو أن بايثون لا تدعم هذا بشكل مباشر ، ولكن يمكن تنفيذه عن طريق التصنيف الفرعي type
صف دراسي.لذلك إضافة خاصية إلى فئة فرعية من type
سوف يسبب مثيلاتها أن يكون واصفات لتلك الخاصية.مثيلاتها هي الطبقات.وهكذا ، واصفات الطبقة.
هل هذا مستحسن?هل هناك أي غوتشاس يجب أن احترس?
المحلول
إنه اصطلاح (عادة) ، بالنسبة للواصف ، عند الوصول إليه في فئة ، لإرجاع كائن الواصف نفسه.هذا هو ما property
هل;إذا قمت بالوصول إلى كائن خاصية في فئة ، فستحصل على كائن الخاصية مرة أخرى (لأن هذا هو ما هو عليه __get__
طريقة يختار القيام به).لكن هذه اتفاقية;ليس عليك أن تفعل ذلك بهذه الطريقة.
لذلك ، إذا كنت بحاجة فقط إلى الحصول على جالبة واصف على صفك ، وكنت لا تمانع في أن محاولة لتعيين سوف الكتابة فوق واصف ، يمكنك أن تفعل شيئا من هذا القبيل مع عدم وجود برمجة ميتاكلاس:
def classproperty_getter_only(f):
class NonDataDescriptor(object):
def __get__(self, instance, icls):
return f(icls)
return NonDataDescriptor()
class Foo(object):
@classproperty_getter_only
def flup(cls):
return 'hello from', cls
print Foo.flup
print Foo().flup
ل
('hello from', <class '__main__.Foo'>)
('hello from', <class '__main__.Foo'>)
إذا كنت تريد واصف بيانات كامل ، أو تريد استخدام كائن الخاصية المدمج ، فأنت على حق يمكنك استخدام ميتاكلاس ووضعه هناك (إدراك أن هذه السمة ستكون غير مرئية تماما من مثيلات صفك;لا يتم فحص ميتاكلاسيس عند القيام بحث السمة على مثيل فئة).
هل من المستحسن?لا أعتقد ذلك.لن أفعل ما تصفه بشكل عرضي في كود الإنتاج;وأود أن تنظر فقط إذا كان لدي سبب مقنع جدا للقيام بذلك (وأنا لا أستطيع التفكير في مثل هذا السيناريو من أعلى رأسي).ميتاكلاسيس هي قوية جدا ، لكنها ليست مفهومة جيدا من قبل جميع المبرمجين ، وأصعب إلى حد ما لسبب حول ، لذلك استخدامها يجعل التعليمات البرمجية الخاصة بك أصعب للحفاظ عليها.أعتقد أن هذا النوع من التصميم سيكون مستاء من قبل مجتمع بايثون ككل.
نصائح أخرى
هل هذا ما تعنيه ب "سمات الطبقة لتكون في الواقع خصائص, الذي يتم التعامل مع أساليب الطبقة الوصول"?
يمكنك استخدام الديكور property
لجعل الوصول يبدو أنه عضو بيانات فعلي.ثم ، يمكنك استخدام x.setter
الديكور لجعل واضعة لتلك السمة.
تأكد من أن ترث من object
, ، أو هذا لن ينجح.
class Foo(object):
def __init__(self):
self._hiddenx = 3
@property
def x(self):
return self._hiddenx + 10
@x.setter
def x(self, value):
self._hiddenx = value
p = Foo()
p.x #13
p.x = 4
p.x #14