2014-04-13 3 views
1

최근에 속성 (예 : property 데코레이터)에 대한 정보를 읽었으며 구현 방법이 마음에 들지 않았습니다. 파이썬. 음, 언어 자체의 내부 부분이 아니라는 것을 알고 있습니다. 예를 들어 C#과 같은 언어로 작성된 것은 아닙니다.하지만 실제로는 더 잘 구현할 수 있다고 생각합니다 (심지어 장식 자와 만). 나는 그것이 구현되어야한다고 생각하는 방식에 대한 개념 증명을 만들고 싶었고 약간의 장애물이있었습니다 (극복 할 수없는 것은 아무것도 아닙니다 ...).기존 파이썬 함수에 코드 줄을 추가하는 방법

다음은 내가 생각한 것입니다. name 속성을 사용하여 Person 클래스가 있다고 가정 해보십시오. 속성을 정의 내 방법과 같습니다

class Person(): 
    def __init__(self, name, age): 
     self._name = name 
     self._age = age 

    @my_property 
    def name(self): 
     def getter(self): 
      return self._name 

     def setter(self, value): 
      self._name = value 

     def deleter(self): 
      del self._name 

     return getter, setter, deleter 

그리고 우리는 다음과 같이 장식 my_property 정의가 :

def my_property(f): 
    d = {g.__name__: g for g in f(None)} 
    p = property(d.get('getter'), d.get('setter'), d.get('deleter')) 
    return p 

지금,이 위대한 작품,하지만 난 정말 있도록하여 그것을 개선하려는

사용자가 명시 적으로 코드 줄을 추가하지 않으려면 : return getter, setter, deleter. 그 대신 데코레이터가이 라인을 함수 f (이 경우에는 name 메소드)에 추가한다고 가정합니다. 코드 객체 f (예 : f.__code__)을 가지고 놀아야 할 것 같지만, 원하는 것을 성취하는 방법을 알 수는 없습니다.

내 속성의 모양은 속성의 C# 구문과 매우 유사합니다. 같은 필드의 getter, setter 및 deleter는 코드의 일부 블록 안에 그룹화되어야한다고 생각합니다. (제 경우에는 함수 정의를 선택했습니다.) 클래스 전체에 분산되어 있지 않아야합니다. 동일한 이름을 가진 경우에도 구문 상 구분됩니다.) ... 더 자세히 말하자면, 저는 지금 정의되어있는 방법이라고 생각합니다 - 먼저 property 데코레이터로 getter를 속성으로 선언 한 다음 getter의 이름을 세터를 장식하고 deleter는 꽤 많이 못생긴다. 하지만 그 날 :)

UPDATE

@User의 대답에 동의 한 후, 나는 내부에서 코드 개체를 받고 자신의 아이디어를 사용하여, 내 재산의 장식을 다시 구현 래퍼 방법의 코드 개체. 여기에 새로운 프로토 타입이있다. 프로토 타입 일 뿐이다. 필자는 property 장식자를 내 장식 자 (원래 property 장식자를 사용함)로 그림자 처리하기로 결정했으나, 원하는대로 호출 할 수 있습니다 ... 전반적으로 생각하면 멋지다. Python에 property 키워드가 있으면 좋겠다. (예 : @ 사용자 대답 그의 대답에서) 메서드 정의 또는 클래스 정의를 사용하는 대신 속성을 정의하는 데 사용됩니다.

def property(f, property=property): 
    from types import CodeType, FunctionType 
    d = {code.co_name: FunctionType(code, f.__globals__) 
     for code in f.__code__.co_consts 
     if type(code) is CodeType} 
    return property(d.get('getter'), d.get('setter'), d.get('deleter'), f.__doc__) 


class Person(): 
    def __init__(self, name, age): 
     self._name = name 
     self._age = age 

    @property 
    def name(): 
     def getter(self): 
      return self._name 
     def setter(self, value): 
      self._name = value 
     def deleter(self): 
      del self._name 

>>> p1 = Person('Name', 25) 
>>> p1.name 
'Name' 
>>> p1.name = "New Name" 
>>> p1.name 
'New Name' 
+2

되는 제목의 질문에 직접 답 : 키보드를 사용합니다. –

+1

그래서'@ property','@ x.setter' 및'@ x.deleter'를 사용해야한다는 사실에 문제가 있습니까? 그게 다야? –

+0

@ Two-BitAlchemist 빈정 거 렸는지, 아니면 진지했다면 어쨌든, 어쩌면 타이틀에 "동적으로"또는 "런타임에"추가해야했을 것입니다. 귀하의 다른 의견에 관해서는, 그것은 나를 귀찮게하는 데코레이터의 다중 사용이 아닙니다. 단지 추한 (또는 귀엽지 않은) 것을 발견하고 클래스에 많은 메소드와 속성이 혼합되어있을 때 혼동을 줄 수 있다고 생각합니다. 서로. – rboy

답변

3

이제 당신은 예뻐 할 수 있습니다 :

>>> def dec(f): 
    import types 
    codes = [] 
    for code in f.__code__.co_consts: 
     if isinstance(code, types.CodeType): 
      codes.append(code) 
    getter = types.FunctionType(codes[0], f.__globals__) 
    setter = types.FunctionType(codes[1], f.__globals__) 
    detter = types.FunctionType(codes[2], f.__globals__) 
    return property(getter, setter, detter, f.__doc__) 

>>> class X: 
    @dec 
    def f(): 
     def g(*args): 
      print('get', args) 
     def h(*args): 
      print('set', args) 
     def j(*args): 
      print('del', args) 


>>> X().f 
get (<__main__.X object at 0x02DFD870>,) 
>>> X().f = 1 
set (<__main__.X object at 0x02E13750>, 1) 
>>> del X().f 
del (<__main__.X object at 0x02DFD870>,) 

내가 당신의 생각에 관심이 있어요.

하지만 어쩌면 클래스 장식

@dec 
class attribute: 
    # ... functions 

아니면도 문을 사용하는 것이 더 나은 것입니다 :

with makeProperty: 
    # ... functions 
+0

나는 그것을 정말로 좋아한다! 나는 코드 객체로 작업하는 것이 매우 새로운데, 그래서 나는 co_consts에 익숙하지 않았다. 함수를 실행하지 않고 다른 코드 객체 내부의 코드 객체에 액세스 할 수 있다는 것을 알면 정말 좋습니다. 나는 class-like 선언이 더 좋을 것이라고 생각하지만 class 키워드는 다소 혼란 스럽다. 만약 파이썬이 키워드'property'를 가지고 있었다면 위대한 것이었을 것입니다. :) 앞에서 말했듯이, 그것은 단지 개념 증명입니다. 만약 내가 그것을 어떻게 사용할 지 모르겠습니다. 그래서 지금은 그렇지 않습니다. 속성을 정의하는 데 '클래스'또는 'def'인 경우에는별로 중요하지 않지만 확실히 더 멋지다! – rboy

+0

그건 그렇고, 나는 get/set/delete 메소드의 순서 변경을 허용하여 코드를 조금 개선했다. 구현시 가져오고 설정 한 다음 삭제해야하며 사용자가 그 중 하나를 생략 할 수 없습니다. 필자는 코드 이름 (즉,'code.co_name')을보고 'getter', 'setter'및 'deleter'(여기에서 명명 규칙을 사용하면 쉽게 이해할 수 있음)을 찾고보다 유연하게 만들었습니다. 내 주요 게시물에 내 원래의 구현과 비슷한 그 이름과'FunctionType' 개체의 사전을 생성. – rboy

+0

한 번 가능하면 코드/결과에 연결하면 좋을 것입니다. :) – User

관련 문제