나는 점점 오전 new_tag
과 양식 텍스트 필드에서 self.response.get("new_tag")
와 selected_tags
와 체크 박스 필드에서
self.response.get_all("selected_tags")
나는 이것을 다음과 같이 결합합니다.
tag_string = new_tag
new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)
( f1.striplist
목록에서 문자열 내부의 공백을 제거하는 기능입니다.)
그러나 경우에 tag_list
비어 (새로운 태그가 입력되지 않습니다)하지만 일부가 selected_tags
, new_tag_list
빈 문자열을 포함합니다 " "
.
예를 들면 다음과 logging.info
같습니다.
new_tag
selected_tags[u'Hello', u'Cool', u'Glam']
new_tag_list[u'', u'Hello', u'Cool', u'Glam']
빈 문자열을 어떻게 제거합니까?
목록에 빈 문자열이있는 경우 :
>>> s = [u'', u'Hello', u'Cool', u'Glam']
>>> i = s.index("")
>>> del s[i]
>>> s
[u'Hello', u'Cool', u'Glam']
그러나 빈 문자열이 없으면 :
>>> s = [u'Hello', u'Cool', u'Glam']
>>> if s.index(""):
i = s.index("")
del s[i]
else:
print "new_tag_list has no empty string"
그러나 이것은 다음을 제공합니다.
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
if new_tag_list.index(""):
ValueError: list.index(x): x not in list
왜 이런 일이 발생하며 어떻게 해결합니까?
답변
1) 거의 영어 스타일 :
in
연산자를 사용하여 존재 여부를 테스트 한 다음 remove
방법 을 적용하십시오 .
if thing in some_list: some_list.remove(thing)
이 remove
방법은 대신 thing
사용할 수있는 모든 항목을 제거하기 위해 첫 번째 항목 만 제거합니다 .while
if
while thing in some_list: some_list.remove(thing)
- 충분히 간단하고 아마도 내 선택. 작은 목록 (한 줄짜리 저항 할 수 없음)
2) 오리 형 , EAFP 스타일 :
이 첫 번째 질문은 마지막 태도는 파이썬에서 일반적입니다. 물체가 적합한 지 미리 테스트하는 대신 작업을 수행하고 관련 예외를 포착하십시오.
try:
some_list.remove(thing)
except ValueError:
pass # or scream: thing not in some_list!
except AttributeError:
call_security("some_list not quacking like a list!")
물론 위의 예에서 두 번째 예외 조항은 의심스러운 유머뿐만 아니라 완전히 불필요합니다 (요점은 개념에 익숙하지 않은 사람들에게 오리 타이핑을 설명하는 것이 었습니다).
여러 번 나타날 것으로 예상되는 경우 :
while True:
try:
some_list.remove(thing)
except ValueError:
break
- 이 특정 사용 사례에 대해서는 조금 장황하지만 파이썬에서는 매우 관용적입니다.
- 이것은 # 1보다 잘 수행됩니다.
- PEP 463 은 여기서는 편리한 간단한 사용법을 제외하고 시도하기위한 더 짧은 구문을 제안했지만 승인되지 않았습니다.
그러나 contextlib의 suppress () contextmanager (파이썬 3.4에서 도입)를 사용하면 위 코드를 다음과 같이 단순화 할 수 있습니다.
with suppress(ValueError, AttributeError):
some_list.remove(thing)
다시 말하지만 여러 번 나타날 것으로 예상되는 경우 :
with suppress(ValueError):
while True:
some_list.remove(thing)
3) 기능적 스타일 :
약 1993 파이썬 가지고 lambda
, reduce()
, filter()
와 map()
하는 의례 리스프 를 놓친 해커 및 제출 작업 패치 *. filter
목록에서 요소를 제거 하는 데 사용할 수 있습니다 .
is_not_thing = lambda x: x is not thing
cleaned_list = filter(is_not_thing, some_list)
빈 항목 (여기서 0, 빈 문자열 또는 다른 빈 컬렉션 bool(item) == False
과 같은 항목)을 필터링하려는 경우 None
첫 번째 인수로 없음을 전달할 수 있습니다.
cleaned_list = filter(None, some_list)
- [update] : Python 2.x에서는 이전
filter(function, iterable)
과 같[item for item in iterable if function(item)]
거나[item for item in iterable if item]
첫 번째 인수가이면None
; Python 3.x에서는 이제와 같습니다(item for item in iterable if function(item))
. 미묘한 차이점은 필터가 목록을 반환하는 데 사용된다는 것입니다. 이제는 생성기 표현식처럼 작동합니다. 정리 된 목록을 반복하고 삭제하는 경우에만 괜찮지 만 목록이 실제로 필요한 경우filter()
호출 을 묶어야합니다.list()
생성자 와 함께 . - *이 Lispy 맛 구조는 Python에서 약간 외계인으로 간주됩니다. 2005 년쯤 귀도는 낙하에 대해 이야기하고있었습니다.
filter
동료들map
과 함께 하고 있었고reduce
(아직 사라지지 않았지만 functools 모듈reduce
로 옮겨졌습니다 .이 기능은 고차 함수 를 좋아한다면 볼만한 가치가 있습니다 ).
4) 수학적 스타일 :
목록 이해 는 PEP 202에 의해 버전 2.0에서 도입 된 이후 파이썬에서리스트 조작에 선호되는 스타일이되었습니다 . 그 뒤에 근거는 목록 함축 어디 상황에서 목록을 만들 수있는 더 간결한 방식으로 제공하는 것입니다 map()
및 filter()
및 / 또는 중첩 루프가 현재 사용되는 것입니다.
cleaned_list = [ x for x in some_list if x is not thing ]
제네레이터 표현식은 버전 2.4에서 PEP 289는 . 생성자 표현식은 한 번에 하나씩 요소를 반복하려는 경우와 같이 메모리에 전체 목록을 만들 필요가 없거나 원하지 않는 상황에 더 좋습니다. 목록을 반복하는 경우 생성기 표현식을 지연된 평가 된 목록 이해 로 생각할 수 있습니다 .
for item in (x for x in some_list if x is not thing):
do_your_thing_with(item)
- GvR 의이 Python history 블로그 게시물을 참조하십시오 .
- 이 구문은 수학 의 set-builder 표기법 에서 영감을 얻었습니다 .
- 파이썬 3도 이해력을 설정 하고 지시했습니다 .
노트
- 부등식 연산자를 사용할 수 있습니다
!=
대신is not
( 차이가 중요합니다 ). - 리스트 카피를 암시하는 방법에 대한 비평가들 : 대중적 신념과는 달리, 생성기 표현이리스트 이해보다 항상 효율적인 것은 아닙니다. 불평하기 전에 프로파일 링하십시오
답변
try:
s.remove("")
except ValueError:
print "new_tag_list has no empty string"
이렇게하면 코드에서와 같이 목록에서 빈 문자열의 인스턴스 하나만 제거됩니다. 목록에 둘 이상을 포함 할 수 있습니까?
답변
경우 index
(가) 문자열을 검색 찾을 수없는, 그것은 던졌습니다 ValueError
당신에게있는 거 보는합니다. ValueError를 포착하십시오.
try:
i = s.index("")
del s[i]
except ValueError:
print "new_tag_list has no empty string"
또는find
이 경우 -1을 반환하는을 사용하십시오 .
i = s.find("")
if i >= 0:
del s[i]
else:
print "new_tag_list has no empty string"
답변
완전성을 위해이 답변을 추가하지만 특정 조건에서만 사용할 수 있습니다.
목록이 매우 큰 경우 목록의 끝에서 제거하면 목록 memmove
을 다시 정렬 할 수있는 상황에서 CPython 내부 에서해야 할 일이 없습니다. 목록의 끝에서 제거하면 성능이 향상됩니다. 제거 후 한 단계 후에 memmove
모든 항목이 필요하지 않기 때문입니다 (1) .
일회성 제거의 경우 성능 차이가 허용 될 수 있지만 큰 목록이 있고 많은 항목을 제거해야하는 경우 성능이 저하 될 수 있습니다.
물론,이 경우 전체 목록 검색을 수행하면 항목이 목록의 맨 앞에 있지 않는 한 성능 병목 현상이 발생할 수 있습니다.
이 방법은
목록을 다시 정렬하는 것이 허용되는 한보다 효율적인 제거를 위해 사용될 수 있습니다 . (2)
def remove_unordered(ls, item):
i = ls.index(item)
ls[-1], ls[i] = ls[i], ls[-1]
ls.pop()
item
가 목록에 없을 때 오류가 발생하지 않도록 할 수 있습니다 .
def remove_unordered_test(ls, item):
try:
i = ls.index(item)
except ValueError:
return False
ls[-1], ls[i] = ls[i], ls[-1]
ls.pop()
return True
- CPython으로 이것을 테스트했지만 대부분의 다른 모든 Python 구현은 배열을 사용하여 목록을 내부적으로 저장합니다. 따라서 효율적인 목록 크기 조정을 위해 설계된 정교한 데이터 구조를 사용하지 않으면 동일한 성능 특성을 가질 수 있습니다.
이것을 테스트하는 간단한 방법은 목록 앞면에서 제거하는 것과 속도 요소를 마지막 요소 제거와 비교하십시오.
python -m timeit 'a = [0] * 100000' 'while a: a.remove(0)'
와:
python -m timeit 'a = [0] * 100000' 'while a: a.pop()'
(CPython 및 PyPy를 사용하여 두 번째 예가 더 빠른 경우 차수의 속도 차이를 나타냅니다).
- 이 경우
set
특히 목록이 중복을 저장하지 않는 경우을 사용하는 것이 좋습니다.
실제로에 추가 할 수없는 가변 데이터를 저장해야 할 수도 있습니다set
. 또한 데이터를 주문할 수 있는지 btree를 확인하십시오.
답변
Eek, 복잡한 일을하지 마십시오 🙂
filter()
태그 만 빈 문자열을 bool()
반환 False
하므로
new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)
당신은 작성해야합니다
new_tag_list = filter(bool, f1.striplist(tag_string.split(",") + selected_tags))
또는 더 나은 방법으로,이 논리를 내부에 넣으면 striplist()
처음에 빈 문자열이 반환되지 않습니다.
답변
여기에 버리는 또 다른 한 줄짜리 접근법이 있습니다.
next((some_list.pop(i) for i, l in enumerate(some_list) if l == thing), None)
목록 복사본을 만들지 않고 목록을 여러 번 통과하지 않고 추가 예외 처리가 필요하지 않으며 일치하는 개체를 반환하거나 일치하지 않는 경우 없음을 반환합니다. 유일한 문제는 그것이 긴 진술을한다는 것입니다.
일반적으로 예외를 발생시키지 않는 한 줄짜리 솔루션을 찾을 때 next ()는 기본 인수를 지원하는 몇 가지 Python 함수 중 하나이기 때문에 갈 길입니다.
답변
당신이해야 할 일은 이것입니다
list = ["a", "b", "c"]
try:
list.remove("a")
except:
print("meow")
그러나 그 방법에는 문제가 있습니다. 내가 이것을 발견했을 때 제외 장소에 무언가를 넣어야합니다.
list = ["a", "b", "c"]
if "a" in str(list):
list.remove("a")