Menu
Coddy logo textTech

요약 - 커스텀 리스트

Coddy Python 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 64개 중 36번째.

challenge icon

챌린지

중급

이 챌린지에서는 파이썬의 내장 리스트 동작을 모방하면서 특수 메서드에 대한 이해를 보여주는 완전한 기능을 갖춘 CustomList 클래스를 구현합니다.

구현을 단계별로 안내하는 TODO 주석에 따라 customlist.py 파일만 수정하세요.

구현해야 할 기능은 다음과 같습니다:

  • 선택적 항목을 포함한 초기화
  • 인덱싱 (값 가져오기/설정하기)
  • len()을 사용한 길이 확인
  • 다른 리스트와의 덧셈
  • 문자열 표현
  • 반복(Iteration) 및 포함 여부 확인
  • 메서드: append, pop, clear

치트 시트

CustomList 클래스는 파이썬의 내장 리스트 동작을 모방하기 위해 특별한 메서드(던더 메서드)를 사용하여 구현할 수 있습니다:

  • __init__(self, items=None) - 선택적 항목으로 초기화
  • __getitem__(self, index) - 값을 가져오기 위한 인덱싱 활성화
  • __setitem__(self, index, value) - 값을 설정하기 위한 인덱싱 활성화
  • __len__(self) - len() 함수 활성화
  • __add__(self, other) - 다른 리스트와의 덧셈 활성화
  • __str__(self) - 문자열 표현
  • __iter__(self) - 반복(iteration) 활성화
  • __contains__(self, item) - in 연산자 활성화

구현할 일반적인 리스트 메서드:

  • append(self, item) - 끝에 항목 추가
  • pop(self, index=-1) - 인덱스의 항목을 제거하고 반환
  • clear(self) - 모든 항목 제거

직접 해보기

from customlist import CustomList


def test_basic_functionality():
    """기본적인 CustomList 기능 테스트"""
    try:
        # 초기화 테스트
        empty_list = CustomList()
        assert len(empty_list) == 0, f"Empty list should have length 0, but has {len(empty_list)}"
        
        init_list = CustomList([1, 2, 3])
        assert len(init_list) == 3, f"Initialized list should have length 3, but has {len(init_list)}"
        
        # 인덱싱 테스트
        assert init_list[0] == 1, f"First element should be 1, but got {init_list[0]}"
        init_list[1] = 10
        assert init_list[1] == 10, f"Element after assignment should be 10, but got {init_list[1]}"
        
        # 문자열 표현 테스트
        assert str(init_list) == "[1, 10, 3]", f"String representation incorrect, got {str(init_list)}"
        
        # 덧셈 테스트
        combined = init_list + CustomList([4, 5])
        assert len(combined) == 5, f"Combined list should have length 5, but has {len(combined)}"
        assert combined[3] == 4, f"Fourth element of combined list should be 4, but got {combined[3]}"
        
        # 반복 및 포함 여부 테스트
        items = []
        for item in combined:
            items.append(item)
        assert items == [1, 10, 3, 4, 5], f"Iteration produced incorrect items: {items}"
        
        assert 10 in combined, "10 should be in the list"
        assert 7 not in combined, "7 should not be in the list"
        
        # append 및 pop 테스트
        combined.append(6)
        assert len(combined) == 6, f"After append, length should be 6, but got {len(combined)}"
        assert combined[5] == 6, f"Last element after append should be 6, but got {combined[5]}"
        
        popped = combined.pop()
        assert popped == 6, f"Popped value should be 6, but got {popped}"
        assert len(combined) == 5, f"After pop, length should be 5, but got {len(combined)}"
        
        # clear 테스트
        combined.clear()
        assert len(combined) == 0, f"After clear, length should be 0, but got {len(combined)}"
        
        print("Basic functionality tests passed!")
        return True
    except Exception as e:
        print(f"Basic functionality test failed: {e}")
        return False


def test_edge_cases():
    """예외 케이스 및 경계 조건 테스트"""
    try:
        # 빈 리스트 연산 테스트
        empty_list = CustomList()
        
        # 빈 리스트에서 pop 테스트
        try:
            empty_list.pop()
            assert False, "pop() on empty list should raise IndexError"
        except IndexError:
            pass  # 예상된 동작
        
        # 빈 리스트에서 인덱싱 테스트
        try:
            value = empty_list[0]
            assert False, "Indexing empty list should raise IndexError"
        except IndexError:
            pass  # 예상된 동작
            
        # None 값 테스트
        none_list = CustomList([None, None])
        assert len(none_list) == 2, f"List with None values should have length 2, got {len(none_list)}"
        assert none_list[0] is None, "First element should be None"
        
        # 혼합 타입 테스트
        mixed_list = CustomList([1, "string", 3.14, [1, 2], {"key": "value"}])
        assert len(mixed_list) == 5, f"Mixed type list should have length 5, got {len(mixed_list)}"
        assert mixed_list[1] == "string", f"Second element should be 'string', got {mixed_list[1]}"
        
        # 일반 리스트와의 덧셈 테스트
        result = mixed_list + [6, 7, 8]
        assert len(result) == 8, f"After adding regular list, length should be 8, got {len(result)}"
        assert result[5] == 6, f"Sixth element should be 6, got {result[5]}"
        
        # 빈 리스트와의 덧셈 테스트
        result = mixed_list + []
        assert len(result) == 5, f"After adding empty list, length should be 5, got {len(result)}"
        assert result[0] == 1, f"First element should still be 1, got {result[0]}"
        
        # repr 테스트
        repr_str = repr(CustomList([1, 2, 3]))
        assert repr_str == "CustomList([1, 2, 3])", f"repr should be 'CustomList([1, 2, 3])', got {repr_str}"
        
        print("Edge case tests passed!")
        return True
    except Exception as e:
        print(f"Edge case test failed: {e}")
        return False


def test_large_lists():
    """대규모 리스트 성능 테스트"""
    try:
        # 대규모 리스트 생성 및 연산 테스트
        # 대규모 리스트 생성
        large_list = CustomList(range(10000))
        assert len(large_list) == 10000, f"Large list should have length 10000, got {len(large_list)}"
        
        # 대규모 리스트 인덱싱 테스트
        assert large_list[9999] == 9999, f"Last element should be 9999, got {large_list[9999]}"
        
        # 대규모 리스트 포함 여부 테스트
        assert 5000 in large_list, "5000 should be in the large list"
        assert 10001 not in large_list, "10001 should not be in the large list"
        
        # 두 대규모 리스트의 덧셈 테스트
        other_large = CustomList(range(10000, 20000))
        combined = large_list + other_large
        assert len(combined) == 20000, f"Combined large lists should have length 20000, got {len(combined)}"
        assert combined[0] == 0, f"First element should be 0, got {combined[0]}"
        assert combined[19999] == 19999, f"Last element should be 19999, got {combined[19999]}"
        
        print("Large list tests passed!")
        return True
    except Exception as e:
        print(f"Large list test failed: {e}")
        return False


def test_nested_lists():
    """중첩된 CustomList 객체 테스트"""
    try:
        # 중첩된 CustomList 객체 테스트
        inner1 = CustomList([1, 2, 3])
        inner2 = CustomList([4, 5, 6])
        outer = CustomList([inner1, inner2, 7])
        
        assert len(outer) == 3, f"Outer list should have length 3, got {len(outer)}"
        assert outer[0] is inner1, "First element should be inner1"
        assert len(outer[0]) == 3, f"First inner list should have length 3, got {len(outer[0])}"
        assert outer[0][1] == 2, f"Second element of first inner list should be 2, got {outer[0][1]}"
        
        # 내부 리스트 수정 테스트
        inner1.append(4)
        assert len(outer[0]) == 4, f"After append, inner list should have length 4, got {len(outer[0])}"
        assert outer[0][3] == 4, f"Fourth element of inner list should be 4, got {outer[0][3]}"
        
        # 중첩된 덧셈 테스트
        result = outer[0] + outer[1]
        assert len(result) == 7, f"Combined inner lists should have length 7, got {len(result)}"
        assert result[0] == 1, f"First element should be 1, got {result[0]}"
        assert result[6] == 6, f"Last element should be 6, got {result[6]}"
        
        print("Nested list tests passed!")
        return True
    except Exception as e:
        print(f"Nested list test failed: {e}")
        return False


def test_custom_operations():
    """사용자 정의 연산 및 조합 테스트"""
    try:
        # 사용자 정의 연산 및 메서드 조합 테스트
        # 체이닝 연산 테스트
        list1 = CustomList([1, 2])
        list2 = CustomList([3, 4])
        list3 = CustomList([5, 6])
        
        # 덧셈 체이닝
        result = list1 + list2 + list3
        assert len(result) == 6, f"Chained addition should have length 6, got {len(result)}"
        assert result[5] == 6, f"Last element should be 6, got {result[5]}"
        
        # append 및 pop 시퀀스 테스트
        test_list = CustomList([1, 2, 3])
        test_list.append(4)
        test_list.append(5)
        assert test_list.pop() == 5, "First pop should return 5"
        assert test_list.pop() == 4, "Second pop should return 4"
        assert len(test_list) == 3, f"After two pops, length should be 3, got {len(test_list)}"
        
        # clear 후 append 테스트
        test_list.clear()
        assert len(test_list) == 0, f"After clear, length should be 0, got {len(test_list)}"
        test_list.append(10)
        assert len(test_list) == 1, f"After append to cleared list, length should be 1, got {len(test_list)}"
        assert test_list[0] == 10, f"Element should be 10, got {test_list[0]}"
        
        # 빈 리스트 더하기 테스트
        empty1 = CustomList()
        empty2 = CustomList()
        empty_sum = empty1 + empty2
        assert len(empty_sum) == 0, f"Sum of empty lists should be empty, got length {len(empty_sum)}"
        
        print("Custom operations tests passed!")
        return True
    except Exception as e:
        print(f"Custom operations test failed: {e}")
        return False


# 선택된 테스트 또는 모든 테스트 실행
test_case = input()

if test_case == "basic":
    test_basic_functionality()
elif test_case == "edge":
    test_edge_cases()
elif test_case == "large":
    test_large_lists()
elif test_case == "nested":
    test_nested_lists()
elif test_case == "custom":
    test_custom_operations()
else:
    print("Invalid test case. Running basic tests by default.")
    test_basic_functionality()

Object Oriented Programming의 모든 레슨