ما هي أسهل, أكثر إيجازا طريقة لجعل السمات المختارة في مثيل تكون للقراءة فقط?

StackOverflow https://stackoverflow.com/questions/125034

  •  02-07-2019
  •  | 
  •  

سؤال

في بيثون ، أريد أن مختارة سبيل المثال سمات الطبقة تكون للقراءة فقط إلى رمز خارج الصف.أريد أن يكون هناك أي وسيلة خارج رمز يمكن تغيير السمة إلا بشكل غير مباشر من خلال التذرع الطرق على سبيل المثال.أريد جملة موجزة.ما هي أفضل طريقة ؟ (أعطي بلدي الحالي أفضل إجابة أدناه...)

هل كانت مفيدة؟

المحلول

يجب عليك استخدام @property الديكور.

>>> class a(object):
...     def __init__(self, x):
...             self.x = x
...     @property
...     def xval(self):
...             return self.x
... 
>>> b = a(5)
>>> b.xval
5
>>> b.xval = 6
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

نصائح أخرى

class C(object):

    def __init__(self):

        self.fullaccess = 0
        self.__readonly = 22 # almost invisible to outside code...

    # define a publicly visible, read-only version of '__readonly':
    readonly = property(lambda self: self.__readonly)

    def inc_readonly( self ):
        self.__readonly += 1

c=C()

# prove regular attribute is RW...
print "c.fullaccess = %s" % c.fullaccess
c.fullaccess = 1234
print "c.fullaccess = %s" % c.fullaccess

# prove 'readonly' is a read-only attribute
print "c.readonly = %s" % c.readonly
try:
    c.readonly = 3
except AttributeError:
    print "Can't change c.readonly"
print "c.readonly = %s" % c.readonly

# change 'readonly' indirectly...
c.inc_readonly()
print "c.readonly = %s" % c.readonly

هذه النواتج:

$ python ./p.py
ج.fullaccess = 0
ج.fullaccess = 1234
ج.readonly = 22
لا يمكن تغيير ج.للقراءة فقط
ج.readonly = 22
ج.readonly = 23

أصابعي حكة لتكون قادرة على القول

    @readonly
    self.readonly = 22

أي استخدام الديكور على سمة.سيكون نظيفة جدا...

وإليك الطريقة:

class whatever(object):
  def __init__(self, a, b, c, ...):
    self.__foobar = 1
    self.__blahblah = 2

  foobar = property(lambda self: self.__foobar)
  blahblah = property(lambda self: self.__blahblah)

(على افتراض foobar و blahblah هي السمات كنت تريد أن تكون للقراءة فقط.) يتبع اثنين ويؤكد سمة اسم تخفي بشكل فعال من خارج الطبقة ، وبالتالي فإن الإصدارات الداخلية لا يمكن الوصول إليها من الخارج.هذا يعمل فقط على نمط جديد دروس وراثة من وجوه لأنه يعتمد على property.

من ناحية أخرى...هذا هو سخيف جدا القيام به.حفظ المتغيرات الخاصة يبدو أن الهوس الذي يأتي من C++ و Java.المستخدمين يجب استخدام واجهة عامة إلى صفك لأنها مصممة تصميما جيدا ، ليس لأنك قوة لهم.

تحرير:يبدو كيفن نشرت بالفعل نسخة مماثلة.

لا توجد وسيلة حقيقية للقيام بذلك.هناك طرق لجعلها أكثر 'صعبة', لكن لا يوجد مفهوم مخفية تماما لا يمكن الوصول إليها سمات الطبقة.

إذا كان الشخص الخاص بك باستخدام فئة لا يمكن الوثوق بها أن تتبع API مستندات, ثم أن هناك مشكلة خاصة بهم.وحماية الناس من يفعل أشياء غبية يعني فقط أن تفعل أكثر تفصيلا ، معقدة ، الإضرار الغباء أن تحاول أن تفعل كل ما لا ينبغي أن يكون في المقام الأول.

هل يمكن استخدام metaclass أن السيارات يلتف طرق (أو سمات الطبقة) التي تتبع اصطلاح التسمية في الخصائص (مأخوذة من دون خجل توحيد أنواع الطبقات في بيثون 2.2:

class autoprop(type):
    def __init__(cls, name, bases, dict):
        super(autoprop, cls).__init__(name, bases, dict)
        props = {}
        for name in dict.keys():
            if name.startswith("_get_") or name.startswith("_set_"):
                props[name[5:]] = 1
        for name in props.keys():
            fget = getattr(cls, "_get_%s" % name, None)
            fset = getattr(cls, "_set_%s" % name, None)
            setattr(cls, name, property(fget, fset))

هذا يتيح لك استخدام:

class A:
    __metaclass__ = autosuprop
    def _readonly(self):
        return __x

أنا على علم بأن ويليام كيلر أنظف حل حتى الآن..ولكن هنا شيء خطرت لي..

class readonly(object):
    def __init__(self, attribute_name):
        self.attribute_name = attribute_name

    def __get__(self, instance, instance_type):
        if instance != None:
            return getattr(instance, self.attribute_name)
        else:
            raise AttributeError("class %s has no attribute %s" % 
                                 (instance_type.__name__, self.attribute_name))

    def __set__(self, instance, value):
        raise AttributeError("attribute %s is readonly" % 
                              self.attribute_name)

وهنا مثال للاستخدام

class a(object):
    def __init__(self, x):
        self.x = x
    xval = readonly("x")

للأسف هذا الحل لا يمكن التعامل مع المتغيرات الخاصة (__ اسمه المتغيرات).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top