2009-06-23 9 views
-1

어떻게 속성 액세스를 파이썬에서 연기합니까?파이썬에서 메소드 호출을 Monkeypatching

def foo(): 
     ... 

    class Bar: 
     ... 

    bar = Bar() 

는 언제든지 bar가 제공 될 것 콜백 foo()에 의해 반환 된 값을 액세스 할 수 있도록 줄을 구현할 수 :

은의 우리가 있다고 가정하자?

bar 이름이 이미 컨텍스트에 존재합니다. 그것이 액세스 의미가 보존되어야하는 이유입니다. 호출 할 수 없으며 클래스의 속성으로 바를 바꿀 수 없습니다. bar 대신 SomeClass.bar을 사용하면 작동하지 않습니다. 나는 모든 것을 그대로 유지할 필요가 있지만, bar이 생성 된 데이터를 즉석에서 참조하도록 프로그램을 변경하십시오. foo().

UPD : 답변을 주셔서 감사합니다.이 유형의 것은 파이썬에서 불가능합니다. 나는 해결 방법을 찾을거야. ,

class Bar: 
    data = property(lambda self: foo()) 


bar = Bar() 
bar.data # calls foo() 
+1

"시간 표시 줄에 액세스 한"정확히 무엇을 의미합니까? 예 : bar의 속성에 액세스 할 때 또는 bar가 다른 것에 할당되었을 때를 의미합니까? –

+2

단어의 의미에서 "게으른"단어가 아닙니다. 이것은 메서드 함수를 "monkeypatching"하므로 일반적인 메서드 함수 본문이 아닌 다른 것을 호출합니다. 귀하가하려는 것을 정확하게 반영하도록 질문을 변경하십시오. –

+0

@Anurag Uniyal : 막대가 다른 것에 지정되면 의미합니다. @ S.Lott : 해결책은 모든 유형의 객체를 'monkeypatching'하는 것과 같습니다 (내 경우 DB 연결). 내가 '게으른'이라는 말은 단순히 '지연 시간'이었습니다. 만약 내가 쓰는다면, bar = baz.bazar라고 부르면, 오브젝트 바의 값이 그 할당보다 빠르지 않은 baz.bazar의 값을 취하기 위해 할당되기를 바란다. 통역사가 bar = baz.bazar에 도달 할 때 bar가 baz.bazar 값을 취하는 경우 정상적인 동작과는 달리 시간 지연이 발생합니다. 좋아, 질문을 변경. – Alex

답변

0

설명해 주셔서 감사합니다.

이것은 작동하지 않습니다. 변수는 대부분의 언어에서 변수이며 함수 호출이 아닙니다. 파이썬에서는 많은 일을 할 수 있지만 그렇게 할 수는 없습니다.

이유는 항상 고유 한 언어 규칙을 가지고 있기 때문입니다. 파이썬에서 하나의 규칙은 변수가 변수라는 것입니다. 변수를 읽거나 (다른 변수를 수정하지 않고) 변수를 읽으면 다음 코드 행에서 똑같을 수 있습니다.

Monkeypatching을 함수 호출로 사용하면이 규칙이 변경됩니다.

원하는 것은 훨씬 더 역동적 인 언어로만 할 수 있습니다. 매크로 처리 시스템이나 변수가없는 언어 같은 것이지만 무엇이든 첨부 할 수있는 레이블과 같은 것입니다. 그러나 이렇게하면 컴파일러 생성이 훨씬 어려워 지므로 완전히 동적입니다. 컴파일러는 프로그램의 모든 코딩을 고려해야합니다.

+0

Python의 property() 함수는 비교 연산자를 명시 적으로 무시할 수 있으므로 원하는 방식으로 변수를 처리 할 수 ​​있습니다. 이것이 왜 받아 들여진 해결책인지 잘 모르겠다. – Cerin

+0

@Chris : 정확하기 때문에. 질문은 객체의 속성이 아닌 변수에 관한 것입니다. 질문을 읽고 일반 변수와 객체의 속성 사이의 차이점을 확인해야합니다. 이를 고려해 보시거나 솔루션 제공 방법에 대한 예를 제공해주십시오. 파이썬 인터프리터 자체를 변경하지 않고서는 안됩니다. 또한 원래 질문에 대한 의견을보십시오. – Juergen

+0

@Chris : 추가 정보 : 질문을 납치하여 원하는대로 해석 할 수 없습니다. 누군가가 "a = bar"에 대한 호출 의미론을 요구할 때 대답에 맞기 만하면 "a = bar()"또는 "a = bar.data"로 변경할 수 없습니다. 누군가가 질문을했고 이것은 답변입니다! 질문에 맞게 변경하지 마십시오! – Juergen

6

난 당신이 foo는 일부 속성 "데이터"를 링크 할 것 같아요 이것은 파이썬에서는 불가능합니다.

class MyClass(object): 
    def __getattr__(self, attr): 
     if attr == 'bar': 
      print 'getting bar... call the foo()!' 
     else: 
      return object.__getattribute__(self, attr) 

    def __setattr__(self, attr, val): 
     if attr == 'bar': 
      print 'bar was set to', val 
     else: 
      object.__setattr__(self, attr, val) 
+1

또한 foo() 값을 메모하면 함수가 순수하다고 간주되므로 두 번째 액세스에서 bar.data를 계산하지 않아야합니다. http://code.activestate.com/recipes/52201/ – drdaeman

2

을 당신은 기본적으로 모듈 네임 스페이스 (어떻게 당신이 그것을 다시 할당 할 것인가?) 변수를 납치 할 수있는 방법을 요구하고 :

0

는 "언제 줄에 액세스 할 때"액세스 어떤 종류의 만드는 것 발신자은 ... :

당신은 당신이 설명 된 동작을 원하는 경우 클래스의 속성 접근을 사용해야합니다 ? 예 : '1 + 바', '바 [5 :]', '바 .func()'등의 작업을 수행하고 있습니까? 매번 Bar() 생성자를 호출합니까?

지금 당장 귀하의 질문은 너무 희미하고 일반적으로 불가능하다고 생각합니다. 그러나 좀 더 구체적이면 우리가 도울 수 있습니다.

0

이게 당신이 찾고 있는게 있니?

>>> def foo(): print('foo() was called'); 
... 
>>> class Bar: 
...  pass; 
... 
>>> bar = Bar(); 
>>> bar.data = foo; 
>>> bar.data() 
foo() was called 
>>> 
+0

이것은 foo가 자체 매개 변수를 취하지 않고 속성이 아니기 때문에 발생합니다. – ebo

0

Bar의 __new__ 메서드를 재정 의하여 임의 코드를 실행하고 새 인스턴스를 반환 할 수 있습니다.참조 :

http://docs.python.org/reference/datamodel.html#object.__new__는 여기에 인위적인 예입니다 :

>>> class Bar(object): 
...  def __new__(cls): 
...    print "Calling Bar.__new__" 
...    return super(Bar, cls).__new__(cls) 
... 
>>> bar = Bar() 
Calling Bar.__new__ 
>>> bar 
<__main__.Bar object at 0x0222B3D0> 

편집 : 나는 당신의 설명이 그를 정리, 원하는 것을 오해. 나는 네가 원하는 것이 가능하다고 생각하지 않는다. 당신이) foo는 (결과를 원하는 경우

0

는 가장 쉬운 방법은이 작업을 수행하는 것입니다 : 다른

foo() 

아무것도 그냥 불필요한 합병증이다. 나는 그것이 합당하지 않을 때까지 당신이 당신의 모범을 지나치게 단순화 시켰다고 생각합니다.

편집 : 좋아, 누군가 elses 코드를 변경하려고합니다. 아니요, 일반적인 방법으로 변수를 메소드로 변환 할 수 없습니다. 다른 변수를 반환 할 객체로 바꿀 수 있습니다. 일종의 파이썬 메소드가 일관되게 호출 될 수있는 방식으로 사용됩니다.

barrio.py : = "문자열의 일종" 바

fool.py :

import random 

class Foo: 
    def __str__(self): 
     return str(random.random()) 

import barrio 
barrio.bar = Foo() 

이제 실행 파이썬 : 인쇄가 를 호출하기 때문에

>>> import fool 
>>> import barrio 

>>> print barrio.bar 
0.783394625457 
>>> print barrio.bar 
0.662363816543 
>>> print barrio.bar 
0.342930701226 
>>> print barrio.bar 
0.781452467433 

이 작동 str은 문자열이 아니기 때문에 객체에 있습니다. 하지만 일반적으로 불가능합니다.

관련 문제