Python 읽기 전용 속성


97

속성이 언제 비공개 여야하는지, 속성을 사용해야하는지 모르겠습니다.

최근에 세터와 게터가 파이썬 적이 지 않으며 속성 데코레이터를 사용해야한다는 것을 읽었습니다. 괜찮아.

그러나 속성이 있으면 클래스 외부에서 설정해서는 안되지만 읽을 수는 있습니다 (읽기 전용 속성). 이 속성은 비공개 여야하고 비공개로하면 밑줄과 같이 의미 self._x합니까? 그렇다면 getter를 사용하지 않고 어떻게 읽을 수 있습니까? 지금 내가 아는 유일한 방법은

@property
def x(self):
    return self._x

그렇게하면 속성을 읽을 수는 obj.x있지만 설정할 수 obj.x = 1없으므로 괜찮습니다.

하지만 설정하지 말아야 할 개체를 설정하는 데 정말로 신경을 써야합니까? 그냥 떠나야 할지도 몰라요. 하지만 다시 obj._x는 읽기 가 사용자에게 이상하기 때문에 밑줄을 사용할 수 없기 때문에 obj.x다시 사용해야합니다.

당신의 의견과 관행은 무엇입니까?


1
속성의 개념은 속성처럼 동작하지만 추가 코드를 가질 수 있다는 것입니다. 당신이 원하는 모든 것이 가치를 얻는 것이라면, 나는 귀찮게하지 않을 것입니다 : 단지 self.x아무도 변하지 않을 것이라고 믿고 사용 하십시오 x. x변경할 수 없는지 확인하는 것이 중요하다면 속성을 사용하십시오.
li.davidm 2013 년

또한 _x전혀 이상하지 않습니다. 관습 적으로 "비공개"를 의미합니다.
li.davidm 2013 년

1
나는 _x에서 읽는 것이 이상하다는 것을 의미했습니다. _x 이름 자체가 아닙니다. 사용자가 _x에서 직접 읽는다면 그는 무책임합니다.
Rafał Łużyński 2013 년

3
중대한! 귀하의 클래스는해야 새로운 스타일의 클래스 에서 상속 즉, object실제로 당신이 설정 중지하려면이 들어 obj.x. 구식 클래스에서는 실제로 obj.x예상치 못한 결과로를 설정할 수 있습니다 .
Ian H

읽기 전용 속성을 갖는 몇 가지 유효한 이유가 있습니다. 하나는 두 개의 다른 (읽기 / 쓰기) 값을 병합하는 값이있는 경우입니다. 메서드에서이 작업을 수행 할 수 있지만 읽기 전용 속성에서도 수행 할 수 있습니다.
philologon

답변:


71

일반적으로 Python 프로그램은 모든 사용자가 성인에 동의한다는 가정하에 작성되어야하며 따라서 스스로 올바르게 사용하는 책임이 있습니다. 그러나 속성을 설정할 수없는 드문 경우 (예 : 파생 값 또는 일부 정적 데이터 소스에서 읽은 값)는 일반적으로 getter 전용 속성이 선호되는 패턴입니다.


26
귀하의 답변이 모순되는 것 같습니다. 사용자가 책임을지고 올바르게 사용해야한다고 말한 다음 속성을 설정할 수있는 것이 이해가되지 않고 getter 속성이 선호되는 방법이라고 말합니다. 제 생각에는 속성을 설정할 수 있거나 설정할 수 없습니다. 유일한 질문은 내가이 속성을 보호해야하는지 아니면 떠나야하는지입니다. 그 사이에 답이 없어야합니다.
Rafał Łużyński

20
아니요, 문자 그대로 값을 설정할 수 없다면 세터를 갖는 것은 말이되지 않는다고 말했습니다. 예를 들어 반경 멤버와 반경에서 파생 된 원주 속성이있는 원 객체가 있거나 여러 getter 전용 속성으로 일부 읽기 전용 실시간 API를 래핑하는 객체가있는 경우입니다. 모순되는 것은 없습니다.
Silas Ray

9
그러나 책임있는 사용자는 말 그대로 설정할 수없는 속성을 설정하려고하지 않습니다. 그리고 다시 책임을지지 않는 사용자는 문자 그대로 설정할 수있는 속성을 설정하고 그의 설정으로 인해 코드의 다른 곳에서 오류를 발생시킵니다. 따라서 결국 두 속성을 모두 설정할 수 없습니다. 두 가지 모두에 속성을 사용해야합니까, 아니면 사용하지 않아야합니까?
Rafał Łużyński 2013 년

8
하지만 책임있는 사용자 말 그대로 설정할 수없는 속성을 설정하려고 해서는 안됩니다 . 프로그래밍에서 어떤 것이 엄격하게 설정 불가능한 값이라면 책임감 있고 현명한 것은 그것이 불가능하다는 것을 확인하는 것입니다. 이 작은 것들은 모두 신뢰할 수있는 프로그램에 기여합니다.
Robin Smith

6
그것은 많은 사람들과 언어가 취하는 입장입니다. 협상 할 수없는 입장이라면 아마도 파이썬을 사용하지 말아야 할 것입니다.
Silas Ray

75

내 2 센트 인 Silas Ray 는 올바른 길을 가고 있지만 예제를 추가하고 싶었습니다. ;-)

Python은 유형이 안전하지 않은 언어이므로 코드를 합리적 (현명한) 사람처럼 사용하려면 항상 코드 사용자를 신뢰해야합니다.

PEP 8 :

비공개 메서드 및 인스턴스 변수에 대해서만 선행 밑줄을 사용하십시오.

클래스에서 '읽기 전용'속성을 가지려면 @property데코레이션 object을 사용할 수 있습니다. 새 스타일 클래스를 사용 하려면에서 상속해야합니다 .

예:

>>> class A(object):
...     def __init__(self, a):
...         self._a = a
...
...     @property
...     def a(self):
...         return self._a
... 
>>> a = A('test')
>>> a.a
'test'
>>> a.a = 'pleh'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

9
Python은 안전하지 않은 유형이 아니라 동적으로 유형이 지정됩니다. 이름 맹 글링은 속임수를 더 어렵게 만드는 것이 아니라 상속이 문제가 될 수있는 시나리오에서 이름 충돌을 방지하기위한 것입니다.
memeplex

3
그러나 여전히이 방법을 사용하여 변경 가능한 객체를 변경할 수 있음을 기억해야합니다. 예를 들어 인 경우 self.__a = []여전히이 작업을 수행 할 수 있으며 a.a.append('anything')작동합니다.
이고르

3
이 대답에 대해 "합리적인 (분명한) 사람"이 무엇인지는 분명하지 않습니다. 합리적인 사람이 할 것이고하지 않을 것이라고 생각하는 일에 대해 더 분명하게 말할 수 있습니까?
winni2k

3
나를 위해 @property 장식을 사용 하면이 답변의 요점이 될 때 객체에서 상속해야합니다 . 감사.
akki

2
@kkm 버그가 코드에 침투하는 것을 허용하지 않는 유일한 방법은 코드를 작성하지 않는 것입니다.
Alechan

58

다음과 같은 가정을 피하는 방법이 있습니다.

모든 사용자는 동의하는 성인이므로 스스로 올바르게 사용할 책임이 있습니다.

아래 내 업데이트를 참조하십시오

를 사용하는 @property것은 매우 장황합니다. 예 :

   class AClassWithManyAttributes:
        '''refactored to properties'''
        def __init__(a, b, c, d, e ...)
             self._a = a
             self._b = b
             self._c = c
             self.d = d
             self.e = e

        @property
        def a(self):
            return self._a
        @property
        def b(self):
            return self._b
        @property
        def c(self):
            return self._c
        # you get this ... it's long

사용

밑줄 없음 : 공개 변수입니다.
밑줄 하나 : 보호 된 변수입니다.
두 개의 밑줄 : 개인 변수입니다.

마지막을 제외하고는 컨벤션입니다. 정말 열심히 노력한다면 이중 밑줄로 변수에 액세스 할 수 있습니다.

그래서 우리는 무엇을합니까? 파이썬에서 읽기 전용 속성을 포기합니까?

보다! read_only_properties구출에 장식 자!

@read_only_properties('readonly', 'forbidden')
class MyClass(object):
    def __init__(self, a, b, c):
        self.readonly = a
        self.forbidden = b
        self.ok = c

m = MyClass(1, 2, 3)
m.ok = 4
# we can re-assign a value to m.ok
# read only access to m.readonly is OK 
print(m.ok, m.readonly) 
print("This worked...")
# this will explode, and raise AttributeError
m.forbidden = 4

물어:

어디에서 read_only_properties오는가?

질문 해 주셔서 감사합니다. 다음은 read_only_properties 의 소스입니다 .

def read_only_properties(*attrs):

    def class_rebuilder(cls):
        "The class decorator"

        class NewClass(cls):
            "This is the overwritten class"
            def __setattr__(self, name, value):
                if name not in attrs:
                    pass
                elif name not in self.__dict__:
                    pass
                else:
                    raise AttributeError("Can't modify {}".format(name))

                super().__setattr__(name, value)
        return NewClass
    return class_rebuilder

최신 정보

이 답변이 그렇게 많은 관심을 끌 것이라고는 결코 예상하지 못했습니다. 놀랍게도 그렇습니다. 이로 인해 사용할 수있는 패키지를 만들게되었습니다.

$ pip install read-only-properties

파이썬 셸에서 :

In [1]: from rop import read_only_properties

In [2]: @read_only_properties('a')
   ...: class Foo:
   ...:     def __init__(self, a, b):
   ...:         self.a = a
   ...:         self.b = b
   ...:         

In [3]: f=Foo('explodes', 'ok-to-overwrite')

In [4]: f.b = 5

In [5]: f.a = 'boom'
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-a5226072b3b4> in <module>()
----> 1 f.a = 'boom'

/home/oznt/.virtualenvs/tracker/lib/python3.5/site-packages/rop.py in __setattr__(self, name, value)
    116                     pass
    117                 else:
--> 118                     raise AttributeError("Can't touch {}".format(name))
    119 
    120                 super().__setattr__(name, value)

AttributeError: Can't touch a

1
이것은 정말 도움이되며 제가하고 싶은 일을 정확히 수행합니다. 감사합니다. 그러나 Python 3을 설치 한 사용자를위한 것입니다. 저는 Python 2.7.8을 사용하고 있으므로 솔루션에 두 가지 사소한 조정을 적용해야합니다. "class NewClass (cls, <b> object <\ b>) :"... "<b> super (NewClass, self) <\ b> .__ setattr __ (이름, 값) ".
Ying Zhang

1
또한 클래스 멤버 변수가 목록과 사전이되도록주의해야합니다. 이러한 방식으로 업데이트되는 것을 실제로 '잠글'수는 없습니다.
Ying Zhang

1
여기에 하나의 개선과 세 가지 문제가 있습니다. 개선 : if..elif..else블록이 필요 if name in attrs and name in self.__dict__: raise Attr...하지 않을 수 있습니다 pass. 문제 1 : 이렇게 장식 된 클래스는 모두 동일한으로 끝나고 __name__해당 유형의 문자열 표현도 균질화됩니다. 문제 2 :이 장식은 모든 사용자 지정 __setattr__. 문제 3 : 사용자는 del MyClass.__setattr__.
TigerhawkT3

단지 언어 일뿐입니다. "아아 ..."는 "말해서 슬프다 ...."라는 뜻이 아니라고 생각합니다.
Thomas Andrews

나를 방해하는 것은 없습니다 object.__setattr__(f, 'forbidden', 42). read_only_properties이중 밑줄 이름 맹 글링으로 처리되지 않는 추가 항목을 볼 수 없습니다 .
L3viathan

4

다음은 읽기 전용 속성에 대한 약간 다른 접근 방식입니다. 초기화해야하기 때문에 한 번만 쓰기 속성이라고 할 수 있습니다. 그렇지 않나요? 객체의 사전에 직접 액세스하여 속성을 수정할 수 있는지 걱정하는 편집증 환자를 위해 "극단적 인"이름 변경을 도입했습니다.

from uuid import uuid4

class Read_Only_Property:
    def __init__(self, name):
        self.name = name
        self.dict_name = uuid4().hex
        self.initialized = False

    def __get__(self, instance, cls):
        if instance is None:
            return self
        else:
            return instance.__dict__[self.dict_name]

    def __set__(self, instance, value):
        if self.initialized:
            raise AttributeError("Attempt to modify read-only property '%s'." % self.name)
        instance.__dict__[self.dict_name] = value
        self.initialized = True

class Point:
    x = Read_Only_Property('x')
    y = Read_Only_Property('y')
    def __init__(self, x, y):
        self.x = x
        self.y = y

if __name__ == '__main__':
    try:
        p = Point(2, 3)
        print(p.x, p.y)
        p.x = 9
    except Exception as e:
        print(e)

좋은. dict_name대신에 엉망으로 만들면 dict_name = "_spam_" + name에 대한 종속성이 제거되고 uuid4디버깅이 훨씬 쉬워집니다.
cz

그러나 p.__dict__['_spam_x'] = 5값을 변경 한다고 말할 수 p.x있으므로 충분한 이름 변경을 제공하지 않습니다.
Booboo

1

첫 번째 솔루션은 읽기 전용 속성을 삭제 한 다음 설정하고 __dict__를 차단하지 않기 때문에 읽기 전용 속성을 만드는 이전 두 가지 답변에 만족하지 않습니다. 두 번째 솔루션은 테스트를 통해 해결할 수 있습니다. 두 번째로 설정 한 값과 동일한 값을 찾아 결국 변경합니다.

이제 코드입니다.

def final(cls):
    clss = cls
    @classmethod
    def __init_subclass__(cls, **kwargs):
        raise TypeError("type '{}' is not an acceptable base type".format(clss.__name__))
    cls.__init_subclass__ = __init_subclass__
    return cls


def methoddefiner(cls, method_name):
    for clss in cls.mro():
        try:
            getattr(clss, method_name)
            return clss
        except(AttributeError):
            pass
    return None


def readonlyattributes(*attrs):
    """Method to create readonly attributes in a class

    Use as a decorator for a class. This function takes in unlimited 
    string arguments for names of readonly attributes and returns a
    function to make the readonly attributes readonly. 

    The original class's __getattribute__, __setattr__, and __delattr__ methods
    are redefined so avoid defining those methods in the decorated class

    You may create setters and deleters for readonly attributes, however
    if they are overwritten by the subclass, they lose access to the readonly
    attributes. 

    Any method which sets or deletes a readonly attribute within
    the class loses access if overwritten by the subclass besides the __new__
    or __init__ constructors.

    This decorator doesn't support subclassing of these classes
    """
    def classrebuilder(cls):
        def __getattribute__(self, name):
            if name == '__dict__':
                    from types import MappingProxyType
                    return MappingProxyType(super(cls, self).__getattribute__('__dict__'))
            return super(cls, self).__getattribute__(name)
        def __setattr__(self, name, value): 
                if name == '__dict__' or name in attrs:
                    import inspect
                    stack = inspect.stack()
                    try:
                        the_class = stack[1][0].f_locals['self'].__class__
                    except(KeyError):
                        the_class = None
                    the_method = stack[1][0].f_code.co_name
                    if the_class != cls: 
                         if methoddefiner(type(self), the_method) != cls:
                            raise AttributeError("Cannot set readonly attribute '{}'".format(name))                        
                return super(cls, self).__setattr__(name, value)
        def __delattr__(self, name):                
                if name == '__dict__' or name in attrs:
                    import inspect
                    stack = inspect.stack()
                    try:
                        the_class = stack[1][0].f_locals['self'].__class__
                    except(KeyError):
                        the_class = None
                    the_method = stack[1][0].f_code.co_name
                    if the_class != cls:
                        if methoddefiner(type(self), the_method) != cls:
                            raise AttributeError("Cannot delete readonly attribute '{}'".format(name))                        
                return super(cls, self).__delattr__(name)
        clss = cls
        cls.__getattribute__ = __getattribute__
        cls.__setattr__ = __setattr__
        cls.__delattr__ = __delattr__
        #This line will be moved when this algorithm will be compatible with inheritance
        cls = final(cls)
        return cls
    return classrebuilder

def setreadonlyattributes(cls, *readonlyattrs):
    return readonlyattributes(*readonlyattrs)(cls)


if __name__ == '__main__':
    #test readonlyattributes only as an indpendent module
    @readonlyattributes('readonlyfield')
    class ReadonlyFieldClass(object):
        def __init__(self, a, b):
            #Prevent initalization of the internal, unmodified PrivateFieldClass
            #External PrivateFieldClass can be initalized
            self.readonlyfield = a
            self.publicfield = b


    attr = None
    def main():
        global attr
        pfi = ReadonlyFieldClass('forbidden', 'changable')
        ###---test publicfield, ensure its mutable---###
        try:
            #get publicfield
            print(pfi.publicfield)
            print('__getattribute__ works')
            #set publicfield
            pfi.publicfield = 'mutable'
            print('__setattr__ seems to work')
            #get previously set publicfield
            print(pfi.publicfield)
            print('__setattr__ definitely works')
            #delete publicfield
            del pfi.publicfield 
            print('__delattr__ seems to work')
            #get publicfield which was supposed to be deleted therefore should raise AttributeError
            print(pfi.publlicfield)
            #publicfield wasn't deleted, raise RuntimeError
            raise RuntimeError('__delattr__ doesn\'t work')
        except(AttributeError):
            print('__delattr__ works')


        try:
            ###---test readonly, make sure its readonly---###
            #get readonlyfield
            print(pfi.readonlyfield)
            print('__getattribute__ works')
            #set readonlyfield, should raise AttributeError
            pfi.readonlyfield = 'readonly'
            #apparently readonlyfield was set, notify user
            raise RuntimeError('__setattr__ doesn\'t work')
        except(AttributeError):
            print('__setattr__ seems to work')
            try:
                #ensure readonlyfield wasn't set
                print(pfi.readonlyfield)
                print('__setattr__ works')
                #delete readonlyfield
                del pfi.readonlyfield
                #readonlyfield was deleted, raise RuntimeError
                raise RuntimeError('__delattr__ doesn\'t work')
            except(AttributeError):
                print('__delattr__ works')
        try:
            print("Dict testing")
            print(pfi.__dict__, type(pfi.__dict__))
            attr = pfi.readonlyfield
            print(attr)
            print("__getattribute__ works")
            if pfi.readonlyfield != 'forbidden':
                print(pfi.readonlyfield)
                raise RuntimeError("__getattr__ doesn't work")
            try:
                pfi.__dict__ = {}
                raise RuntimeError("__setattr__ doesn't work")
            except(AttributeError):
                print("__setattr__ works")
            del pfi.__dict__
            raise RuntimeError("__delattr__ doesn't work")
        except(AttributeError):
            print(pfi.__dict__)
            print("__delattr__ works")
            print("Basic things work")


main()

라이브러리 코드를 작성할 때를 제외하고는 읽기 전용 속성을 만들 필요가 없습니다 . 앱 개발과 같은 다른 목적을위한 코드가 아니라 프로그램을 향상시키기 위해 다른 사람에게 코드로 배포되는 코드입니다. __dict__는 이제 불 변형 유형 이기 때문에 __dict__ 문제가 해결 되었습니다. 따라서 __dict__를 통해 속성을 변경할 수 없습니다. __dict__ 설정 또는 삭제도 차단됩니다. 읽기 전용 속성을 변경하는 유일한 방법은 클래스 자체의 메서드를 변경하는 것입니다.

내 솔루션이 이전 두 가지보다 낫다고 생각하지만 개선 될 수 있습니다. 다음은이 코드의 약점입니다.

a) 읽기 전용 속성을 설정하거나 삭제하는 하위 클래스의 메서드에 추가하는 것을 허용하지 않습니다. 서브 클래스에 정의 된 메서드는 메서드의 수퍼 클래스 버전을 호출하더라도 읽기 전용 속성에 액세스 할 수 없도록 자동으로 차단됩니다.

b) 클래스의 읽기 전용 메서드를 변경하여 읽기 전용 제한을 무효화 할 수 있습니다.

그러나 읽기 전용 속성을 설정하거나 삭제하기 위해 클래스를 편집하지 않고는 방법이 없습니다. 이것은 명명 규칙에 의존하지 않습니다. 파이썬이 명명 규칙과 그렇게 일치하지 않기 때문에 좋습니다. 이것은 클래스 자체를 편집하지 않고는 숨겨진 허점으로 변경할 수없는 읽기 전용 속성을 만드는 방법을 제공합니다. 데코레이터를 인수로 호출 할 때 읽기 전용 속성을 나열하면 읽기 전용이됩니다.

Python의 다른 클래스 함수 내에서 호출자 클래스 이름을 얻는 방법에 대한 Brice의 답변에 대한 크레딧은 무엇입니까? 호출자 클래스 및 메서드를 가져옵니다.


object.__setattr__(pfi, 'readonly', 'foobar')클래스 자체를 편집하지 않고이 솔루션을 중단합니다.
L3viathan

0

인스턴스 메서드도 (클래스의) 속성이며, 정말 나쁜 사람이되고 싶다면 클래스 또는 인스턴스 수준에서 설정할 수 있습니다. 또는 편리한 읽기 전용 속성이 즉시 작동하지 않는 클래스 변수 (클래스의 속성이기도 함)를 설정할 수도 있습니다. 내가 말하려는 것은 "읽기 전용 속성"문제가 실제로 일반적으로 인식되는 것보다 더 일반적이라는 것입니다. 다행스럽게도 이러한 다른 경우에 대해 우리를 눈 멀게 할 정도로 강한 기존의 기대가 있습니다 (결국 거의 모든 것이 파이썬에서 일종의 속성입니다).

이러한 기대를 바탕으로 가장 일반적이고 가벼운 접근 방식은 "공개"(선행 밑줄 없음) 속성이 쓰기 가능으로 명시 적으로 문서화되는 경우를 제외하고는 읽기 전용이라는 규칙을 채택하는 것이라고 생각합니다. 이것은 메서드가 패치되지 않을 것이라는 일반적인 기대와 인스턴스 기본값을 나타내는 클래스 변수가 더 낫다는 것을 포함합니다. 특별한 속성에 대해 정말로 편집증이라고 느끼면 읽기 전용 설명자를 마지막 리소스 측정으로 사용하십시오.


0

나는 Oz123의 클래스 데코레이터를 좋아하지만, 클로저 내에서 클래스를 반환하는 클래스 Factory 메서드와 함께 명시 적 클래스 래퍼와 __new__를 사용하는 다음을 수행 할 수도 있습니다.

class B(object):
    def __new__(cls, val):
        return cls.factory(val)

@classmethod
def factory(cls, val):
    private = {'var': 'test'}

    class InnerB(object):
        def __init__(self):
            self.variable = val
            pass

        @property
        def var(self):
            return private['var']

    return InnerB()

여러 속성에서 작동하는 방법을 보여주는 테스트를 추가해야합니다
Oz123

0

그것이 내 해결 방법입니다.

@property
def language(self):
    return self._language
@language.setter
def language(self, value):
    # WORKAROUND to get a "getter-only" behavior
    # set the value only if the attribute does not exist
    try:
        if self.language == value:
            pass
        print("WARNING: Cannot set attribute \'language\'.")
    except AttributeError:
        self._language = value

0

누군가 프록시 객체를 사용한다고 언급했지만 그 예를 보지 못해서 결국 시도해 보았습니다. [불량].

/! \ 가능하면 클래스 정의와 클래스 생성자를 선호하십시오

이 코드는 class.__new__모든면에서 더 나쁜 것을 제외하고 는 효과적으로 재 작성 (클래스 생성자)입니다. 고통을 덜어주고 가능하다면이 패턴을 사용하지 마십시오.

def attr_proxy(obj):
    """ Use dynamic class definition to bind obj and proxy_attrs.
        If you can extend the target class constructor that is 
        cleaner, but its not always trivial to do so.
    """
    proxy_attrs = dict()

    class MyObjAttrProxy():
        def __getattr__(self, name):
            if name in proxy_attrs:
                return proxy_attrs[name]  # overloaded

            return getattr(obj, name)  # proxy

        def __setattr__(self, name, value):
            """ note, self is not bound when overloading methods
            """
            proxy_attrs[name] = value

    return MyObjAttrProxy()


myobj = attr_proxy(Object())
setattr(myobj, 'foo_str', 'foo')

def func_bind_obj_as_self(func, self):
    def _method(*args, **kwargs):
        return func(self, *args, **kwargs)
    return _method

def mymethod(self, foo_ct):
    """ self is not bound because we aren't using object __new__
        you can write the __setattr__ method to bind a self 
        argument, or declare your functions dynamically to bind in 
        a static object reference.
    """
    return self.foo_str + foo_ct

setattr(myobj, 'foo', func_bind_obj_as_self(mymethod, myobj))

-2

이 스레드를 죽은 상태에서 되 돌리는 것을 알고 있지만 속성을 읽기 전용으로 만드는 방법을 찾고 있었고이 주제를 찾은 후에 이미 공유 된 솔루션에 만족하지 못했습니다.

따라서이 코드로 시작하면 초기 질문으로 돌아갑니다.

@property
def x(self):
    return self._x

X를 읽기 전용으로 만들려면 다음을 추가하면됩니다.

@x.setter
def x(self, value):
    raise Exception("Member readonly")

그런 다음 다음을 실행하면 :

print (x) # Will print whatever X value is
x = 3 # Will raise exception "Member readonly"

3
그냥 세터을하지 않는 경우에, 할당하려고하는 것이 아니라 (과 같은 오류가 발생합니다 AttributeError('can't set attribute'))
Artyer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.