2014-02-06 4 views
4
[ this question에서 영감]

함수와 같은 변수

나는 두 개의 목록이 있다고 가정

list1 = ['tom', 'mary', 'frank', 'joe', 'john', 'barry'] 
list2 = [1, 2, 3, 4] 

내가 list2의 숫자로 list1 각각의 이름과 일치하도록합니다. list2에는 네 개의 숫자가 있으므로 첫 번째 네 개의 이름 각각을 list2에 대응하는 번호와 쌍으로하고 나머지 이름에 난수를 list1에 할당하고 싶습니다.

for 루프를 사용하여 enumeraterandom.choice을 사용하여이 문제를 해결할 수 있음을 알고 있습니다. 실제로 원래 문제에 such a solution을 제공했습니다.

for name, number in itertools.izip_longest(list1, list2, fillvalue=MAGIC): 
    print name, number 

원래, 나는이 같은 것을 사용하여 생각 : : 그러나

MAGIC = random.choice(list1) 

random.choice(list1) 먼저 수행하는, 그것을 이런 식으로 뭔가를 할 수있는 경우
나는, 그러나 알고 싶습니다 압축을 위해 대답을 fillvalue으로 사용합니다. 이 방법은 각 값 쌍에 대해 새로운 임의 값을 선택하지 않으므로 매력적이지 않습니다. 그러므로 itertools.izip_longestfillvalue을 요구하는데, 그 자체가 값을 가지고있는 것은 아닙니다. 사실, 만약 내가 함수를 제공한다면, 이름과 callable 함수로 구성된 한쌍을 만들어 낼 것이다. 이러한 이유로 lambda 함수는 실행 가능한 솔루션이 아닙니다.

호출 될 때 일부 함수를 호출하는 변수를 만드는 방법은 무엇입니까? itertools.izip_longestfillvalue 변수를 어떻게 사용합니까? 해당 변수의 __repr__이 호출 되었습니까? 그렇다면 그 안에 함수를 호출하는 __repr__ 클래스를 만들 수 있습니까? , inf_gen(f)iter(f, None) 실제로 동등

def inf_gen(f): 
    while True: 
     yield f() 

참고한다 :

+2

"호출 할 때 일부 함수를 호출하는 변수를 만드는 방법은 어떻게됩니까?" - 그러지 않을거야. 함수를 호출합니다. – user2357112

+0

속성을 사용하여 객체 속성에 대해 원하는 것을 얻을 수 있습니다. Python 3에서는 불쾌한 메타 클래스 매직을 사용하여 클래스 범위에서 원하는 것을 얻을 수 있지만 일반 변수의 경우에는 할 수 없습니다. – user2357112

+0

@ user2357112 : 그렇습니다. 그러나 많은 클래스의 인스턴스는 "called"할 때'__repr__' 값을 보여줍니다. 따라서'__repr__'이 어떤 외부 함수를 호출한다면, 갑자기 함수를 사용하여 값을 결정하는 인스턴스를 보유하는 변수가 생깁니다. 그렇지 않으면 변수와 함수의 차이점에 대해 잘 알고 있습니다. – inspectorG4dget

답변

8

후리스트 2의 값을 산출하여이 사슬 영원히 모든 충전제 값을 산출 발전기를 만들 것이다 여기 간단한 방법을 보인다 주어진 f 절대로 반환합니다. 두 개의 인수가있는 iter은 두 번째 인수를 반환 할 때까지 첫 번째 인수를 호출합니다.

다음과 같은 사용 :

>>> from itertools import izip, chain 
>>> for name, number in izip(list1,chain(list2, iter(lambda: random.choice(list2), None))): 
    print name, number 

tom 1 
mary 2 
frank 3 
joe 4 
john 1 
barry 4 

당신은 또한 단지 itertools 물건이 할 수있는 별도의 기능을 정의하지 않고 발전기의 이해를 사용하여 itertools.count로 :

>>> from itertools import izip, chain, count 
>>> for name, number in izip(list1, chain(list2, (random.choice(list2) for _ in count()))): 
    print name, number 
+0

'iter'의 두 인자 형식은 본질적으로'inf_gen'입니다. – chepner

+0

@chepner : 오, 멋지다! 완전히 iter 잊어 버렸습니다. 대답을 업데이트 할 것입니다 – Claudiu

3

당신이 그것을 원하는 경우 여러 개의 반복자에 대해 "확장"하려면 http://docs.python.org/2.7/library/itertools.html?highlight=izip_longest#itertools.izip_longest에 주어진 코드를 약간 수정하면됩니다.

from itertools import repeat, chain, count 

class ZipExhausted(Exception): 
    pass 

def izip_longest2(*args, **kwds): 
    fillvalue = kwds.get('fillvalue') 
    fillgen = kwds.get('fillgen', repeat(fillvalue)) # added 
    counter = [len(args) - 1] 
    def sentinel(): 
     if not counter[0]: 
      raise ZipExhausted 
     counter[0] -= 1 
     yield next(fillgen) # modified 
    iterators = [chain(it, sentinel(), fillgen) for it in args] # modified 
    try: 
     while iterators: 
      yield tuple(map(next, iterators)) 
    except ZipExhausted: 
     pass 


a = ['bob', 'mary', 'paul'] 
b = ['eggs', 'spam'] 
c = ['a', 'b', 'c', 'd'] 

for x in izip_longest2(a, b, c, fillgen=count()): 
    print '\t'.join(map(str, x)) 

# output: 
# bob eggs a 
# mary spam b 
# paul 0 c 
# 1 2 d 
+1

들여 쓰기를 수정하십시오? – inspectorG4dget

+0

EDIT : 고정 들여 쓰기, 그것을 가르쳐 주셔서 감사합니다, @ inspectorG4dget –

+0

이것은 실제로 아주 훌륭합니다! 고맙습니다 :) – inspectorG4dget