클래스 메소드에서 property () 사용


173

본질적으로 정적 변수를 가져오고 설정하기위한 두 가지 클래스 메소드 (classmethod () 함수 사용)가있는 클래스가 있습니다. 이것들과 함께 property () 함수를 사용하려고 시도했지만 오류가 발생합니다. 인터프리터에서 다음과 같은 오류를 재현 할 수있었습니다.

class Foo(object):
    _var = 5
    @classmethod
    def getvar(cls):
        return cls._var
    @classmethod
    def setvar(cls, value):
        cls._var = value
    var = property(getvar, setvar)

클래스 메서드를 보여줄 수는 있지만 속성으로 작동하지는 않습니다.

>>> f = Foo()
>>> f.getvar()
5
>>> f.setvar(4)
>>> f.getvar()
4
>>> f.var
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable
>>> f.var=5
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable

클래스 메소드 장식 함수와 함께 property () 함수를 사용할 수 있습니까?

답변:


90

속성은 클래스에서 만들어 지지만 인스턴스에 영향을줍니다. 따라서 classmethod 속성을 원하면 메타 클래스에 속성을 만드십시오.

>>> class foo(object):
...     _var = 5
...     class __metaclass__(type):  # Python 2 syntax for metaclasses
...         pass
...     @classmethod
...     def getvar(cls):
...         return cls._var
...     @classmethod
...     def setvar(cls, value):
...         cls._var = value
...     
>>> foo.__metaclass__.var = property(foo.getvar.im_func, foo.setvar.im_func)
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3

그러나 어쨌든 메타 클래스를 사용하고 있으므로 클래스 메소드를 이동하면 더 잘 읽을 수 있습니다.

>>> class foo(object):
...     _var = 5
...     class __metaclass__(type):  # Python 2 syntax for metaclasses
...         @property
...         def var(cls):
...             return cls._var
...         @var.setter
...         def var(cls, value):
...             cls._var = value
... 
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3

또는 Python 3의 metaclass=...구문과 foo클래스 본문 외부에 정의 된 메타 클래스 및 초기 값을 설정하는 메타 클래스를 사용합니다 _var.

>>> class foo_meta(type):
...     def __init__(cls, *args, **kwargs):
...         cls._var = 5
...     @property
...     def var(cls):
...         return cls._var
...     @var.setter
...     def var(cls, value):
...         cls._var = value
...
>>> class foo(metaclass=foo_meta):
...     pass
...
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3

1
이것은 Python 3.2에서 작동하지 않는 것 같습니다. foo .__ metaclass __. var = property (foo.getvar.im_func, foo.setvar.im_func)를 foo .__ metaclass __. var = property (foo.getvar .__ func__, foo.setvar .__ func__)로 변경하면 "AttributeError : type "foo.var"를 실행할 때 'foo'개체에 'var' "속성이 없습니다.
Michael Kelley

SIGH 이중 수정 : 이것은 Python 2.7에서는 작동하지만 Python 3.2에서는 작동하지 않습니다.
Michael Kelley

@MichaelKelley- 메타 클래스
mac

1
나는 이것을 이해하는 파이썬 3.x 방법이 무엇인지 이해하지 못한다.
SylvainD

8
@Josay : 먼저 메타 클래스를 정의한 다음 새 class Foo(metaclass=...)구문을 사용하여 클래스를 정의해야 합니다.
Kevin

69

Python 2.2 릴리스 정보를 읽으면 다음을 찾을 수 있습니다.

속성이 인스턴스 속성 (C (). x)이 아닌 클래스 속성 (Cx)으로 액세스되면 속성의 get 메서드가 호출되지 않습니다. 클래스 속성으로 사용될 때 특성에 대한 __get__ 조작을 대체하려는 경우 특성을 서브 클래스 (새 스타일 유형 자체)로 __get__ 메소드를 확장하거나 새로 작성하여 디스크립터 유형을 처음부터 정의 할 수 있습니다. __get__, __set__ 및 __delete__ 메소드를 정의하는 스타일 클래스.

참고 : 아래 방법은 실제로 setter에는 적용되지 않으며 getter에만 적용됩니다.

따라서 처방 된 솔루션은 ClassProperty를 속성의 하위 클래스로 만드는 것입니다.

class ClassProperty(property):
    def __get__(self, cls, owner):
        return self.fget.__get__(None, owner)()

class foo(object):
    _var=5
    def getvar(cls):
        return cls._var
    getvar=classmethod(getvar)
    def setvar(cls,value):
        cls._var=value
    setvar=classmethod(setvar)
    var=ClassProperty(getvar,setvar)

assert foo.getvar() == 5
foo.setvar(4)
assert foo.getvar() == 4
assert foo.var == 4
foo.var = 3
assert foo.var == 3

그러나 세터는 실제로 작동하지 않습니다.

foo.var = 4
assert foo.var == foo._var # raises AssertionError

foo._var 변경되지 않은 상태에서 속성을 새 값으로 덮어 썼습니다.

ClassProperty데코레이터로 사용할 수도 있습니다 .

class foo(object):
    _var = 5

    @ClassProperty
    @classmethod
    def var(cls):
        return cls._var

    @var.setter
    @classmethod
    def var(cls, value):
        cls._var = value

assert foo.var == 5

20
나는 ClassProperty의 setter 부분이 실제로 설명 된대로 작동한다고 생각하지 않습니다. 예제 어설 션이 모두 foo._var == 4 (암시 적 3이 아님) 끝에 전달됩니다. 속성을 설정하면 속성 자체가 클로버됩니다. python-dev 에서 클래스 속성에 대해 논의했을 때 getter는 사소한 반면 메타 클래스가 없으면 setter가 어렵습니다 (불가능합니까?)
Gabriel Grant

4
@Gabriel 완전히 맞습니다. 나는 2 년 동안 아무도 그것을 지적하지 않았다.
agf

또한 왜 당신이 여기를 전혀 사용하지 않아도 self.fget(owner)되고 사용하지 않는지 잘 모르겠습니다 @classmethod. (무엇의 것을 classmethod 않으며 , 번역 .__get__(instance, owner)(*args, **kwargs)function(owner, *args, **kwargs)중개자를 통해 호출, 속성은 중개 필요하지 않습니다).
Martijn Pieters

귀하의 데모에는 게터 또는 세터에서 실제 변환이 부족하여 foo.var = 3할당 이 실제로 속성을 거치지 않고 속성 객체를 foo정수 로 바꿨다는 것을 깔끔하게 보여줍니다 . assert isinstance(foo.__dict__['var'], ClassProperty)어설 션 사이 에 호출 을 추가 하면 실패 후 foo.var = 3가 실행되는 것을 볼 수 있습니다.
Martijn Pieters

1
파이썬 클래스는 설정에 대한 구속력 지원 설명을 클래스 자체에 전용하는 것에 대한 (그래서 instance.attr, instance.attr = value그리고 del instance.attr모든 바인드 기술자는에 발견 할 것이다 type(instance),하지만 반면 classobj.attr바인딩, classobj.attr = value그리고 del classobj.attr않습니다 하지 대체 또는 설명 개체 자체를 삭제하고 대신). 설정 및 삭제를 지원하려면 메타 클래스가 필요합니다 (클래스 객체를 인스턴스로 만들고 메타 클래스를 유형으로 만들기).
Martijn Pieters

56

이 단순한 단순 읽기 전용 @classproperty데코레이터가 누군가 클래스 속성을 찾는 데 도움 이되기를 바랍니다 .

class classproperty(object):

    def __init__(self, fget):
        self.fget = fget

    def __get__(self, owner_self, owner_cls):
        return self.fget(owner_cls)

class C(object):

    @classproperty
    def x(cls):
        return 1

assert C.x == 1
assert C().x == 1

2
서브 클래스에서도 작동합니까? (하위 클래스가 클래스 속성을 재정의 할 수 있습니까?)
zakdances

1
음? class D(C): x = 2; assert D.x == 2
dtheodor

나는 이것을 다음 .format과 같이 사용할 때 효과가 있었으면 좋겠다 "{x}".format(**dict(self.__class__.__dict__, **self.__dict__)):(
2rs2ts

@Nathan뿐만 아니라 ... 설정하면의 모든 x액세스 권한 을 무시합니다 10. 이 방법처럼 나는 안티 패턴처럼 단정하고 간단하지만 소리 때문에
미셸 다 미코

쉽게 고정하십시오 추가 __set__가 제기하는 ValueError재정의를 방지 할 수 있습니다.
Kiran Jonnalagadda

30

클래스 메소드 장식 함수와 함께 property () 함수를 사용할 수 있습니까?

아니.

그러나 클래스 메소드는 단순히 해당 클래스의 인스턴스에서 액세스 할 수있는 클래스의 바인딩 된 메소드 (일부 함수)입니다.

인스턴스는 클래스의 함수이므로 인스턴스에서 클래스를 파생시킬 수 있으므로 다음을 사용하여 클래스 속성에서 원하는 동작을 얻을 수 있습니다 property.

class Example(object):
    _class_property = None
    @property
    def class_property(self):
        return self._class_property
    @class_property.setter
    def class_property(self, value):
        type(self)._class_property = value
    @class_property.deleter
    def class_property(self):
        del type(self)._class_property

이 코드는 테스트하는 데 사용될 수 있습니다. 오류없이 발생해야합니다.

ex1 = Example()
ex2 = Example()
ex1.class_property = None
ex2.class_property = 'Example'
assert ex1.class_property is ex2.class_property
del ex2.class_property
assert not hasattr(ex1, 'class_property')

그리고 우리는 메타 클래스가 전혀 필요하지 않았으며 클래스의 인스턴스를 통해 메타 클래스에 직접 액세스하지 않습니다.

@classproperty데코레이터 작성

classproperty서브 클래 싱을 통해 몇 줄의 코드로 데코레이터를 실제로 만들 수 있습니다 property(C로 구현되었지만 여기에서 동등한 Python을 볼 수 있습니다 ).

class classproperty(property):
    def __get__(self, obj, objtype=None):
        return super(classproperty, self).__get__(objtype)
    def __set__(self, obj, value):
        super(classproperty, self).__set__(type(obj), value)
    def __delete__(self, obj):
        super(classproperty, self).__delete__(type(obj))

그런 다음 데코레이터를 속성과 결합 된 클래스 메소드처럼 취급하십시오.

class Foo(object):
    _bar = 5
    @classproperty
    def bar(cls):
        """this is the bar attribute - each subclass of Foo gets its own.
        Lookups should follow the method resolution order.
        """
        return cls._bar
    @bar.setter
    def bar(cls, value):
        cls._bar = value
    @bar.deleter
    def bar(cls):
        del cls._bar

그리고이 코드는 오류없이 작동해야합니다.

def main():
    f = Foo()
    print(f.bar)
    f.bar = 4
    print(f.bar)
    del f.bar
    try:
        f.bar
    except AttributeError:
        pass
    else:
        raise RuntimeError('f.bar must have worked - inconceivable!')
    help(f)  # includes the Foo.bar help.
    f.bar = 5

    class Bar(Foo):
        "a subclass of Foo, nothing more"
    help(Bar) # includes the Foo.bar help!
    b = Bar()
    b.bar = 'baz'
    print(b.bar) # prints baz
    del b.bar
    print(b.bar) # prints 5 - looked up from Foo!

    
if __name__ == '__main__':
    main()

그러나 이것이 얼마나 잘 충고되었는지는 확실하지 않습니다. 오래된 메일 링리스트 기사에 따르면 작동하지 않아야합니다.

강의실에서 숙소를 이용하기 :

위의 단점은 "클래스 속성"은 클래스에서 데이터 디스크립터를 덮어 쓰기 때문에 클래스에서 액세스 할 수 없다는 것 __dict__입니다.

그러나 metaclass에 정의 된 속성으로이를 재정의 할 수 있습니다 __dict__. 예를 들면 다음과 같습니다.

class MetaWithFooClassProperty(type):
    @property
    def foo(cls):
        """The foo property is a function of the class -
        in this case, the trivial case of the identity function.
        """
        return cls

그런 다음 메타 클래스의 클래스 인스턴스는 이전 섹션에서 이미 설명한 원칙을 사용하여 클래스의 속성에 액세스하는 속성을 가질 수 있습니다.

class FooClassProperty(metaclass=MetaWithFooClassProperty):
    @property
    def foo(self):
        """access the class's property"""
        return type(self).foo

이제 우리는 두 인스턴스를 모두 본다

>>> FooClassProperty().foo
<class '__main__.FooClassProperty'>

그리고 수업

>>> FooClassProperty.foo
<class '__main__.FooClassProperty'>

클래스 속성에 액세스 할 수 있습니다.


3
명확하고 간결하며 철저한 답변입니다. 이것은 정답입니다.
pfabri

25

파이썬 3!

오래된 질문, 많은 견해, 진실한 파이썬 3 방법이 절실히 필요합니다.

운 좋게도 metaclasskwarg를 사용하면 쉽습니다.

class FooProperties(type):

    @property
    def var(cls):
        return cls._var

class Foo(object, metaclass=FooProperties):
    _var = 'FOO!'

그때, >>> Foo.var

'FOO!'


1
즉, 상자 밖으로 나가는 간단한 방법이 없습니다
mehmet

@mehmet 이것은 간단하지 않습니까? Foo은 메타 클래스의 인스턴스이며의 인스턴스와 @property마찬가지로 메소드에 사용할 수 있습니다 Foo.
OJFord

2
메타 클래스를 재사용 할 수 없다고 가정하면 클래스의 다른 클래스를 정의해야했습니다.
mehmet

클래스 메소드는 클래스와 인스턴스 모두에서 작동합니다. 이 속성은 클래스에서만 작동합니다. 나는 이것이 요구되는 것이라고 생각하지 않습니다.
Aaron Hall

1
@AaronHall 중요하다면,에 쉽게 추가 할 수 있습니다 Foo.__new__. 그 시점에서 getattribute를 대신 사용하거나 언어 기능을 가장하는 것이 실제로 어떤 접근 방법인지 질문하는 것이 좋습니다.
OJFord

16

이 "클래스 속성"시스템을 파이썬에서 작동시키는 합리적인 방법은 없습니다.

그것이 작동하게하는 불합리한 방법은 다음과 같습니다. 메타 클래스 마법의 양을 늘리면 더 매끄럽게 만들 수 있습니다.

class ClassProperty(object):
    def __init__(self, getter, setter):
        self.getter = getter
        self.setter = setter
    def __get__(self, cls, owner):
        return getattr(cls, self.getter)()
    def __set__(self, cls, value):
        getattr(cls, self.setter)(value)

class MetaFoo(type):
    var = ClassProperty('getvar', 'setvar')

class Foo(object):
    __metaclass__ = MetaFoo
    _var = 5
    @classmethod
    def getvar(cls):
        print "Getting var =", cls._var
        return cls._var
    @classmethod
    def setvar(cls, value):
        print "Setting var =", value
        cls._var = value

x = Foo.var
print "Foo.var = ", x
Foo.var = 42
x = Foo.var
print "Foo.var = ", x

문제의 핵심은 속성이 파이썬이 "설명자"라고 부르는 것입니다. 이러한 종류의 메타 프로그래밍이 어떻게 작동하는지 설명 할 수있는 짧고 쉬운 방법은 없으므로 설명자 howto 를 알려야합니다. .

상당히 고급 프레임 워크를 구현하는 경우 이러한 종류의 것들만 이해하면됩니다. 투명한 객체 지속성 또는 RPC 시스템 또는 일종의 도메인 별 언어와 같습니다.

그러나 이전 답변에 대한 의견에서 귀하는

클래스의 모든 인스턴스에서 볼 수있는 방식으로 속성을 수정해야하며 이러한 클래스 메소드가 호출되는 범위에 클래스의 모든 인스턴스에 대한 참조가 없습니다.

당신이 정말로 원하는 것은 관찰자 디자인 패턴입니다.


코드 예제의 아이디어가 마음에 들지만 실제로는 약간 어색한 것 같습니다.
Mark Roddy

내가 성취하려고하는 것은 모든 인스턴스의 동작을 수정하기위한 플래그로 사용되는 단일 속성을 얻는 것입니다. 따라서 Observer가 내가하려는 일에 과장되어 있다고 생각합니다. 문제의 속성이 여러 개인 경우 더 기울어 질 것입니다.
Mark Roddy

단순히 함수를 공개하고 직접 호출하는 것이 단순한 솔루션이었습니다. 내가 잘못하고 있거나 노력하고 있는지가 궁금했습니다. 그런데 여러 의견에 대해 죄송합니다. 300 자 제한.
Mark Roddy

코드 예제의 멋진 점은 모든 복잡한 비트를 한 번 구현 한 다음 상속 할 수 있다는 것입니다. _var을 파생 클래스로 옮기십시오. 클래스 D1 (푸) : _var = 21 개 클래스 D2 (푸) _var = "안녕하세요"D1.var 21 D2.var 안녕하세요
토마스 L Holaday

6

메타 클래스에서만 설정하면 인스턴스화 된 객체를 통해 클래스 속성에 액세스하려는 경우 도움이되지 않습니다.이 경우 객체에 일반 속성을 설치해야합니다 (클래스 속성으로 디스패치). 다음은 조금 더 분명하다고 생각합니다.

#!/usr/bin/python

class classproperty(property):
    def __get__(self, obj, type_):
        return self.fget.__get__(None, type_)()

    def __set__(self, obj, value):
        cls = type(obj)
        return self.fset.__get__(None, cls)(value)

class A (object):

    _foo = 1

    @classproperty
    @classmethod
    def foo(cls):
        return cls._foo

    @foo.setter
    @classmethod
    def foo(cls, value):
        cls.foo = value

a = A()

print a.foo

b = A()

print b.foo

b.foo = 5

print a.foo

A.foo = 10

print b.foo

print A.foo

3

절반의 솔루션 인 __set__은 여전히 ​​작동하지 않습니다. 솔루션은 속성과 정적 메서드를 모두 구현하는 사용자 지정 속성 클래스입니다.

class ClassProperty(object):
    def __init__(self, fget, fset):
        self.fget = fget
        self.fset = fset

    def __get__(self, instance, owner):
        return self.fget()

    def __set__(self, instance, value):
        self.fset(value)

class Foo(object):
    _bar = 1
    def get_bar():
        print 'getting'
        return Foo._bar

    def set_bar(value):
        print 'setting'
        Foo._bar = value

    bar = ClassProperty(get_bar, set_bar)

f = Foo()
#__get__ works
f.bar
Foo.bar

f.bar = 2
Foo.bar = 3 #__set__ does not

3

클래스의 모든 인스턴스에서 볼 수있는 방식으로 이러한 클래스 메소드가 호출되는 범위에서 속성을 수정해야하기 때문에 클래스의 모든 인스턴스에 대한 참조가 없습니다.

수업 중 하나 이상의 인스턴스에 액세스 할 수 있습니까? 그때 할 수있는 방법을 생각할 수 있습니다.

class MyClass (object):
    __var = None

    def _set_var (self, value):
        type (self).__var = value

    def _get_var (self):
        return self.__var

    var = property (_get_var, _set_var)

a = MyClass ()
b = MyClass ()
a.var = "foo"
print b.var

2

시도해보십시오. 기존 코드를 많이 변경 / 추가하지 않고도 작업을 수행 할 수 있습니다.

>>> class foo(object):
...     _var = 5
...     def getvar(cls):
...         return cls._var
...     getvar = classmethod(getvar)
...     def setvar(cls, value):
...         cls._var = value
...     setvar = classmethod(setvar)
...     var = property(lambda self: self.getvar(), lambda self, val: self.setvar(val))
...
>>> f = foo()
>>> f.var
5
>>> f.var = 3
>>> f.var
3

property함수에는 두 개의 callable인수 가 필요합니다 . 람다 래퍼 (인스턴스를 첫 번째 인수로 전달)를 제공하면 모든 것이 잘됩니다.


Florian Bösch가 지적했듯이 (타사 라이브러리 또는 레거시 코드에 필요한) 구문은 foo.var입니다.
Thomas L Holaday

2

다음은 클래스를 통한 액세스와 메타 클래스를 사용하는 인스턴스를 통한 액세스 모두에서 작동해야하는 솔루션입니다.

In [1]: class ClassPropertyMeta(type):
   ...:     @property
   ...:     def prop(cls):
   ...:         return cls._prop
   ...:     def __new__(cls, name, parents, dct):
   ...:         # This makes overriding __getattr__ and __setattr__ in the class impossible, but should be fixable
   ...:         dct['__getattr__'] = classmethod(lambda cls, attr: getattr(cls, attr))
   ...:         dct['__setattr__'] = classmethod(lambda cls, attr, val: setattr(cls, attr, val))
   ...:         return super(ClassPropertyMeta, cls).__new__(cls, name, parents, dct)
   ...:

In [2]: class ClassProperty(object):
   ...:     __metaclass__ = ClassPropertyMeta
   ...:     _prop = 42
   ...:     def __getattr__(self, attr):
   ...:         raise Exception('Never gets called')
   ...:

In [3]: ClassProperty.prop
Out[3]: 42

In [4]: ClassProperty.prop = 1
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-e2e8b423818a> in <module>()
----> 1 ClassProperty.prop = 1

AttributeError: can't set attribute

In [5]: cp = ClassProperty()

In [6]: cp.prop
Out[6]: 42

In [7]: cp.prop = 1
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-7-e8284a3ee950> in <module>()
----> 1 cp.prop = 1

<ipython-input-1-16b7c320d521> in <lambda>(cls, attr, val)
      6         # This makes overriding __getattr__ and __setattr__ in the class impossible, but should be fixable
      7         dct['__getattr__'] = classmethod(lambda cls, attr: getattr(cls, attr))
----> 8         dct['__setattr__'] = classmethod(lambda cls, attr, val: setattr(cls, attr, val))
      9         return super(ClassPropertyMeta, cls).__new__(cls, name, parents, dct)

AttributeError: can't set attribute

메타 클래스에 정의 된 setter 와도 작동합니다.


1

다른 장소를 검색 한 후 Python 2 및 3에서 유효한 클래스 속성을 정의하는 방법을 찾았습니다.

from future.utils import with_metaclass

class BuilderMetaClass(type):
    @property
    def load_namespaces(self):
        return (self.__sourcepath__)

class BuilderMixin(with_metaclass(BuilderMetaClass, object)):
    __sourcepath__ = 'sp'        

print(BuilderMixin.load_namespaces)

이것이 누군가를 도울 수 있기를 바랍니다 :)


1
이 방법이 당신이 어딘가에서 찾은 것이라면, 링크를 제공하는 것이 좋을 것입니다 ( 다른 사람들이 쓴 자료를 참조하는 방법 참조 )
Andrew Myers

-27

여기 내 제안이 있습니다. 클래스 메소드를 사용하지 마십시오.

진심으로.

이 경우 클래스 메소드를 사용하는 이유는 무엇입니까? 왜 평범한 수업의 평범한 물건이 없습니까?


단순히 값을 변경하려는 경우 속성이 그다지 도움이되지 않습니까? 속성 값을 설정하고 완료하십시오.

감추어 야 할 것이 있다면, 미래 구현에서 변경 될 수있는 것만 사용해야합니다.

어쩌면 귀하의 예가 끝났을 수도 있고, 끝내지 못한 계산이있을 수도 있습니다. 그러나 속성이 상당한 가치를 부여하는 것처럼 보이지 않습니다.

Java에 영향을 미치는 "개인 정보 보호"기술 (Python에서 _로 시작하는 속성 이름)은 그다지 도움이되지 않습니다. 누구 한테서? (Python에서와 같이) 소스를 가지고있을 때 개인의 관점은 조금 성가시다.

Java에 영향을 미치는 EJB 스타일 getter 및 setter (종종 Python의 특성으로 수행됨)는 정적 언어 컴파일러를 사용하여 소집자를 전달할뿐만 아니라 Java의 원시적 인트로 스펙 션을 용이하게합니다. 그 게터와 세터는 모두 파이썬에서 도움이되지 않습니다.


14
클래스의 모든 인스턴스에서 볼 수있는 방식으로 이러한 클래스 메소드가 호출되는 범위에서 속성을 수정해야하기 때문에 클래스의 모든 인스턴스에 대한 참조가 없습니다.
Mark Roddy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.