2009-07-16 4 views
14

장소에서 int 객체를 증가하는 파이썬 방법이 있나요, INT가 __iadd__을 구현하지 않는 것은 너무 + = 1은 실제로 새로운 객체를 반환증가 int 객체

>>> n=1 
>>> id(n) 
9788024 
>>> n+=1 
>>> id(n) 
9788012 

내가 원하는 것은 남아 n은 같은 대상을 가리키고있다.

목적 : 나는 INT에서 파생 된 클래스를하고 난

결론 C 유형을 구현하는 클래스에 대한 '++ N'연산자를 원하는 : 내가해야 할 것 같은 INT는 방법은 없습니다 불변 확인으로, 보이는 내 자신의 클래스를 이런 식으로 작성하십시오.

class Int(object): 
    def __init__(self, value): 
     self._decr = False 
     self.value = value 

    def __neg__(self): 
     if self._decr: 
      self.value -= 1 
     self._decr = not self._decr 
     return self 

    def __str__(self): 
     return str(self.value) 

    def __cmp__(self, n): 
     return cmp(self.value, n) 

    def __nonzero__(self): 
     return self.value 

n = Int(10) 
while --n: 
    print n 
+0

왜 당신이 그것을 위해 접두사 연산자를 구현하고자합니까? ++ n을 메소드 호출로 변환하기 위해 사용자 정의 전 처리기를 추가 할 예정입니까? – Ryan

+1

흠 그냥 파이썬이 할 수있는 친구를 보여주고 싶습니다. --n : print n;) –

+0

익명의 클래스 (변경 가능)에서 int를 래핑하는 약간의 복잡한 방법으로 이것을 보시고 'reference': http://stackoverflow.com/a/1123054/409638 ref = type ('', ('n': 1)) – robert

답변

12

의 int는 불변입니다.

+5

해당 클래스의 int는 여전히 변경 불가능합니다. –

+1

클래스의 int가 불변 인 경우 속성의 값이 가변적이므로 아무런 효과가 없으므로 원하는 MutableInt 클래스를 정의 할 수 있습니다. –

+0

이 작업을 수행했습니다 : https://github.com/markrages/python_mutable_number – markrages

3

int 메소드를 구현하고 내부 정수를 래핑하는 클래스를 만드는 것이 더 쉽습니다. 당신이

+1

더 쉬울뿐만 아니라 int가있는 유일한 방법 일 수도 있습니다 변경할 수 없음 – Arkady

0

예, 짧은 대답이의 int는 불변한다는 것입니다 당신이 "가변 INT"를 원하는 경우 모든 INT의 방법으로 자신의 클래스를 구축해야합니다 있도록

3

코드를 작동 시키려면 반드시 인스턴스 메서드가 프레임을 위로 이동하고 자체 locals 항목을 덮어 쓰는 더러운 메서드를 사용해야합니다. 추천하지 않았어. (예를 들어, 정말로 그렇지 않다. 나는 그것이 무엇 인지도 모르지만, 예전 인스턴스는 어떻게 될 것인가? 프레임에 대해 충분히 알지 못한다 ...). 사실, 모든 사람이 그것이 불가능하다고 말했기 때문에 나는 단지 이것을 게시하고 있습니다. 실제로 그것은 엄청나게 나쁜 형태입니다. ;-)

import sys 
class FakeInt(int): 
    def __init__(self, *arg, **kwarg): 
     self._decr = False 
     int.__init__(self, *arg, **kwarg) 
    def __neg__(self): 
     if self._decr: 

      upLocals = sys._getframe(1).f_locals 
      keys, values = zip(*upLocals.items()) 
      i = list(values).index(self) 

      result = FakeInt(self-1) 
      upLocals[keys[i]]=result 

      return result 
     self._decr = not self._decr 
     return self 

A = FakeInt(10) 
while --A: 
    print A, 

출력 :

9 8 7 6 5 4 3 2 1 
+0

관련없는 참고 사항, 먼저 목록으로 변환하지 않고 튜플에있는 항목의 색인을 찾을 수 있는지 아는 사람 있습니까? i = list (values) .index (self)는 조금 우회하는 것처럼 보입니다. – Markus

+2

+1 흥미 롭습니다. 그렇지만 나는 이것을 사용하기가 무섭습니다. –

+0

@ Markus a = (1,2,3,4,5); a.index (3)의 결과는 2입니다. 적어도 이것은 파이썬 3과 같습니다. –

2

넌 가변 컨테이너 내부 불변 오브젝트를 넣을 수; 목록이 가장 쉽습니다.

이 코드 인쇄 0 문제 시연 : 당신이 목록에있는 INT를 넣어하지만, 그 이전과 같은 코드를 사용하는 경우

a = 0  # `a` points to a new int (a `0`) 
b = a  # `b` points to the same thing as `a` (the `0`) 
b = 1  # `b` points to a new int (a `1`) 
print(a) # `a` still points to the same thing (the `0`) 

, 당신은하지만 (변경 가능한 INT 데의 효과를 얻을 수 있습니다 실제로 돌연변이 된 목록입니다.) :

a = [0]  # `a` points to a new `0` inside a new list 
b = a   # `b` points to the same thing as `a` (the list) 
b[0] = 1  # the list that `a` and `b` point to is mutated 
print(a[0]) # `a[0]` points to the same object as `b[0]` (the `1`) 

실제로 '위의 트릭'이 중복되도록 데이터를 구조해야합니다. 예제를 직접 사용해서는 안되지만 수행 할 작업을 파악하는 데 도움이됩니다.

4

변경할 수있는 정수로 ctypes를 사용할 수 있습니다. 올바른 ctype을 선택하는 것은 중요 할 수 있습니다. 즉, 그들이 운반 할 수있는 정수의 크기를 제한하기 때문입니다.

>>> from ctypes import c_int64 
>>> num = c_int64(0) 
>>> id(num) 
4447709232 
>>> def increment(number): 
...  number.value += 1 
... 
>>> increment(num) 
>>> increment(num) 
>>> increment(num) 
>>> num.value 
3 
>>> id(num) 
4447709232 
>>> 

더 많은 정보는 :

+0

레코드의 경우 이것은 정상적인 정수를 증가시키는 것보다 느립니다. – Zaz

+0

몇 가지 이유 때문에 아마 나쁜 생각이지만, 어쨌든 고마워, 이제는 'mutable_int'를 가져올 수있는 차선책을 알고 있습니다. – Daerdemandt

0

https://docs.python.org/2/library/ctypes.html#fundamental-data-types는 오늘 유사한 문제가 있었다 당신이 "+"를 사용하여 증가 또는 감소 장소에서 할 수 IterInt라는 클래스를 내놓았다 "-"데코레이터.

사용법 :

내가 특정 인덱스 후 몇 명령 항목을 삽입하여 응용 프로그램의 기존 메뉴를 수정하고 싶었 상황을 가지고 내 경우에는
x = IterInt() 

print x 
# result: 0 

print +x 
# result: 1 

print +x 
# result: 2 

print +x 
# result: 3 

print -x 
# result: 2 

print -x 
# result: 1 

print -x 
# result: 0 

.제공된 API에는 삽입 할 인덱스를 취할 수있는 "addCommand"함수가 있습니다.

메뉴 메뉴 = [A, F, G] 같은 g를 통해, 어떤 명령이이 의사 코드를 고려, 나는 1-4

idx = 1 
menu.addCommand(b, index=idx) 
idx += 1 
menu.addCommand(c, index=idx) 
idx += 1 
menu.addCommand(d, index=idx) 
idx += 1 
menu.addCommand(e, index=idx) 
idx += 1 

# result: menu = [a, b, c, d, e, f] 

그것은 좋은 것 인덱스 할 삽입 할 내가 idx ++를 할 수있는 곳에서 idx를 증가시킬 수 있다면 cx처럼 쓸 수는 있지만 함수는 인수에서 python의 idx + = 1 방법론을 허용하지 않습니다.

솔루션 :

class IterInt(int): 
""" 
This function will return the next integer from the init_value starting point or 0 if None. 
Each subsequent call to increment returns the next value 
:param init_value: 
:return: 
""" 
def __init__(self, init_value=None): 
    if init_value is None: 
     init_value = 0 

    if init_value is not None: 
     self.increment_value = init_value 
    self.increment_value = init_value 

def __pos__(self): 
    self.increment_value += 1 
    return self.increment_value 

def __neg__(self): 
    self.increment_value -= 1 
    return self.increment_value 


idx = IterInt(1) 
menu.addCommand(b, index=+idx) 
menu.addCommand(c, index=+idx) 
menu.addCommand(d, index=+idx) 
menu.addCommand(e, index=+idx) 

# result: menu = [a, b, c, d, e, f] 
관련 문제