2012-03-08 3 views
3

나는 다음과 같은 코드에 대한 몇 가지 질문이 있습니다부동산 파이썬에서 장식 및 설정 기능

1 class Test(object): 
    2  def __init__(self): 
    3   print "Object instance created." 
    4   self._x = raw_input("Initial value of x = ") 
    5   print "Initial value of x set." 
    6 
    7  def Property(func): 
    8   return property(**func()) 
    9 
10  @Property 
11  def x(): 
12   def fget(self): 
13    print 'Getting x' 
14    return self._x 
15   def fset(self, val): 
16    print 'Setting x' 
17    self._x = val 
18   def fdel(self): 
19    print 'Deleting x' 
20    del self._x 
21   doc = "A test case" 
22   return locals() 
  1. Property() 기능이 필요하세요?
  2. 그냥 return locals()을 입력 한 다음 @property을 데코레이터로 직접 사용할 수 없습니까?

내가 그렇게 할 때 x는 아무런 인자도 없으며 (아마도 '자기'라고) 말합니다. 나는 파이썬이 @x.setter 옵션을 가지고 있다는 것을 알고 있지만, 나는 2.4를 정기적으로 사용해야하므로 선택 사항이 아니다. 그렇더라도 은 여전히 ​​하나의 블록에서 모두를 정의하는 것보다 덜 우아합니다.

@property을 사용하여 한 블록에 모두 정의 할 수 있습니까?

+0

본인의 실제 해결 방법이 마음에 듭니다. 사용을 시작할 수 있습니다! :) –

답변

2

그런 식으로 사용하도록 설계되지 않았기 때문에 게시 한 코드에 데코레이터로 property을 직접 사용할 수 없으며 작동하지 않습니다.

데코레이터로 사용되는 경우 property은 게터로 기능을 변환합니다. 함수로 사용되면 getter, setter, deleter 및 doc을 전달할 수 있습니다.

locals() 반환 모든 주민, 당신이 사전을 것이다 있도록 fget, fset, fdel, doc, Property__init__ - 너무 많은 인수를 전달하기 때문에 날려 property의 원인.

필자는 개인적으로 클래스 이름 공간에 불필요한 함수 이름이 없기 때문에 개인적으로 @x.setter@x.deleter 스타일을 좋아합니다.

당신은 자신의 롤, 정기적 2.4을 사용하는 경우 (또는 내가 그랬던 것처럼 2.6에서 최신을 훔치는) :

class property(object): 
     "2.6 properties for 2.5-"  
     def __init__(self, fget=None, fset=None, fdel=None, doc=None): 
      self.fget = fget 
      self.fset = fset 
      self.fdel = fdel 
      self.__doc__ = doc or fget.__doc__ 
     def __call__(self, func): 
      self.fget = func 
      if not self.__doc__: 
       self.__doc__ = fget.__doc__ 
     def __get__(self, obj, objtype=None): 
      if obj is None: 
       return self   
      if self.fget is None: 
       raise AttributeError("unreadable attribute") 
      return self.fget(obj) 
     def __set__(self, obj, value): 
      if self.fset is None: 
       raise AttributeError("can't set attribute") 
      self.fset(obj, value) 
     def __delete__(self, obj): 
      if self.fdel is None: 
       raise AttributeError("can't delete attribute") 
      self.fdel(obj) 
     def setter(self, func): 
      self.fset = func 
      return self 
     def deleter(self, func): 
      self.fdel = func 
      return self 
+0

답장을 보내 주셔서 감사합니다. '@ x.setter'와'@ x.deleter'가없는 최선의 방법은'property'를 데코레이터로 사용하지 않는 것일 수 있다고 생각합니다.'x = property (xget, xset, xdel, xdoc)'라고 말하고 클래스의 세 함수를 정의하기 위해 첫 번째 게시물의 해킹보다 적은 수의 행을 사용합니다. 나는 이것이 내가 앞으로 끝내게 될 것이라고 생각한다. – Mikey08

2

당신 한 블록에서 모든 작업을 수행 할 수 없습니다 사용하여 @property__get__(), __set__()__delete__() 메서드가있는 클래스를 정의하고 인스턴스화하면됩니다. 자세한 내용은 Implementing Descriptors를 참조하십시오

class Test(object): 
    def __init__(self): 
     print "Object instance created." 
     self._x = raw_input("Initial value of x = ") 
     print "Initial value of x set." 
    class x(object): 
     def __get__(self, instance, owner): 
      print 'Getting x' 
      return instance._x 
     def __set__(self, instance, value): 
      print 'Setting x' 
      instance._x = value 
     def __delete__(self, instance): 
      print 'Deleting x' 
      del instance._x 
     __doc__ = "A test case" 
    x = x() 

property() 위를 기록에 대한 바로 가기, 그리고 귀하의 예제 클래스의 Property() 방법은 별도로 함수를 작성하고 property()에 전달하는 데에 대한 바로 가기입니다; 대신 함수를 정의한 함수를 작성한 다음 반환하여 property()으로 전달합니다.

@property을 사용할 수없는 이유는 데코레이터가 단일 개체를 장식한다는 것입니다. 따라서 클래스와 같은 컨테이너가 필요하므로 해당 지점에서 직접 설명자를 작성할 수도 있습니다.

+0

+1 설명을 위해,하지만 난 그렇게하지 않을 것이다 :'x'는 인스턴스화되어야하고, 마지막에는 분명하다. 데코레이터는 부분적으로 함수/클래스 정의에 가까운 인스턴스화를 유지하기 위해 만들어졌다. 쉽게 놓치지 않을 것입니다. –

+0

그래, 나는'x = x()'로 쓰는 것을 다소 괴롭혔다. 더 나쁜 것은'x = X(); 델 엑스'.. – kindall