Post

파이썬 문법 꿀팁 100선

파이썬 문법 꿀팁 100선

Towards Data Science에 실렸던 「100 Helpful Python Tips You Can Learn Before Finishing Your Morning Coffee」의 번역 글. (모닝 커피 마시는 동안 배울 수 있는 100개의 파이썬 팁…?) 원문은 현재 삭제된 상태다.

이해를 돕기 위해 일부 내용은 수정/보완했고, 내가 옮겨 적으면서 기억하려고 남기는 글이기에, 개인적으로 유용한 것에는 ⭐ 표시를 붙였다.

1. for-else 문

보통 프로그래밍 언어에서 ‘else’라고 하면 if와 함께 오는 경우가 대부분이다. 하지만 파이썬에서는 for 문과도 함께 쓸 수도 있다.

for문이 중간에 break 등으로 끊기지 않고 끝까지 수행 되었을 때 수행하는 코드를 담으면 된다. else는 for와 같은 수준으로 들여쓰기 해야 한다.

1
2
3
4
5
6
7
8
numbers = [2, 4, 1, 8, 6]

for number in numbers:
    if number % 2 == 1:
        print(number)
        break
else:
    print("No odd numbers")

위 예시는 리스트에 홀수가 있으면 반복문을 중단하는 코드. 홀수가 없으면 문자열이 출력되지만, 이 경우에는 홀수 1이 출력되고, 반복문이 중단된다.

for-else는 반복문이 중간에 break 되었는지 판별해야 하는 경우에 유용하다.

2. 변수명을 나열하여 리스트에서 요소들을 각각 가져오기

1
2
my_list = [1, 2, 3, 4, 5]
one, two, three, four, five = my_list

3. heapq를 사용하여 리스트에서 n개의 가장 큰/작은 요소를 가져오기⭐

heapq는 파이썬 내장 모듈이다.

1
2
3
4
5
6
import heapq

scores = [51, 33, 64, 87, 91, 75, 15, 49, 33, 82]

print(heapq.nlargest(3, scores))  # [91, 87, 82]
print(heapq.nsmallest(5, scores))  # [15, 33, 33, 49, 51]

이걸 응용하면 딕셔너리에서도 key나 value를 기준으로 가장 큰, 가장 작은 값을 가져올 수 있다.

1
2
3
4
5
6
7
8
9
scores = {"a": 51, "b": 33, "c": 64, "d": 87, "e": 91, "f": 75, "g": 15, "h": 49, "i": 33, "j": 82}

# sort by keys
print(heapq.nlargest(3, scores))  # ['j', 'i', 'h']
print(heapq.nsmallest(3, scores))  # ['a', 'b', 'c']

# sort by values
print(heapq.nlargest(3, scores.items(), key=lambda item: item[1]))  # [('e', 91), ('d', 87), ('j', 82)]
print(heapq.nsmallest(3, scores.items(), key=lambda item: item[1]))  # [('g', 15), ('b', 33), ('i', 33)]

4. 리스트에 * 사용하여 처리하기

*를 사용하여 리스트의 모든 요소를 추출할 수 있다.

1
2
3
4
my_list = [1, 2, 3, 4]
print(my_list)  # [1, 2, 3, 4]

print(*my_list)  # 1 2 3 4

이 방법은 리스트의 모든 요소를 메서드 인수로 전달하려는 상황에서 유용하다.

1
2
3
4
5
6
7
8
9
10
def sum_of_elements(*arg):
    total = 0
    for i in arg:
        total += i

    return total


result = sum_of_elements(*[1, 2, 3, 4])
print(result)  # 10

5. 리스트 중간 있는 요소 가져오기

리스트에서 위치를 기준으로 앞이나, 뒤의 요소들을 잘라서 가져오는 신기한 방법.

_*를 사용한다.

1
2
3
4
5
_, *elements_in_the_middle, _ = [1, 2, 3, 4, 5, 6, 7, 8]
print(elements_in_the_middle)  # [2, 3, 4, 5, 6, 7]

_, _, *elements_in_the_middle, _,  _ = [1, 2, 3, 4, 5, 6, 7, 8]
print(elements_in_the_middle)  # [3, 4, 5, 6]

6. 한 줄에서 변수 여러개 할당

1
one, two, three, four = 1, 2, 3, 4

7. 리스트 컴프리헨션 ⭐

리스트 컴프리헨션은 반복문을 한 줄로 처리할 수 있는 우아한 문법이다.

1
2
3
4
5
numbers = [1, 2, 3, 4, 5, 6, 7, 8]

even_numbers = [number for number in numbers if number % 2 == 0]

print(even_numbers)  # [2, 4, 6, 8]

리스트 컴프리헨션은 딕셔너리에서도 활용할 수 있다.

1
2
3
4
5
dictionary = {'first_element': 1, 'second_element': 2,
              'third_element': 3, 'fourth_element': 4}
odd_value_elements = {key: num for (key, num) in
                      dictionary.items() if num % 2 == 1}
print(odd_value_elements)  # {'first_element': 1, 'third_element': 3}

8. enum을 사용해 동일한 개념의 항목 반복하기

파이썬 공식문서 enum 설명

An Enum(https://docs.python.org/ko/3/library/enum.html#enum.Enum) is a set of symbolic names bound to unique values. They are similar to global variables, but they offer a more useful repr()(https://docs.python.org/ko/3/library/functions.html#repr), grouping, type-safety, and a few other features.

1
2
3
4
5
6
7
8
9
10
from enum import Enum

class Status(Enum):
    NO_STATUS = -1
    NOT_STARTED = 0
    IN_PROGRESS = 1
    COMPLETED = 2

print(Status.IN_PROGRESS.name)  # IN_PROGRESS
print(Status.COMPLETED.value)  # 2

9. 연산자 * 활용하여 문자열 반복하기

1
2
3
string = "Abc"

print(string * 5)  # AbcAbcAbcAbcAbc

10. 숫자 3개 한 줄에서 비교하기

파이썬에서는 1 < x and x < 10 과 같은 비교를 한 줄로 처리할 수 있다.

1
2
x = 3
print(1 < x < 10)   # True

11. |를 사용하여 딕셔너리 병합하기 ⭐

파이썬 3.9부터 사용 가능한 문법.

1
2
3
4
5
6
first_dictionary = {'name': 'Fatos', 'location': 'Munich'}
second_dictionary = {'name': 'Fatos', 'surname': 'Morina', 'location': 'Bavaria, Munich'}

result = first_dictionary | second_dictionary
print(result)  
# {'name': 'Fatos', 'location': 'Bavaria, Munich', 'surname': 'Morina'}

12. 튜플에서 특정 요소의 인덱스 찾기

1
2
3
books = ('Atomic habits', 'Ego is the enemy', 'Outliers', 'Mastery')

print(books.index('Mastery'))   # 3

13. 문자열 형식의 리스트를 진짜 리스트로 변환하기

이렇게 리스트처럼 생긴 문자열을 [1,2,3] 진짜 리스트 [1,2,3]로 바꾸고 싶을 때… 생각보다 간단하지 않다.

물론 복잡한 정규식을 쓸 수도 있겠지만, ast 모듈에서 literal_eval 메서드를 사용하면 편하게 처리할 수 있다.

1
2
3
4
5
6
7
8
import ast

def string_to_list(string):
    return ast.literal_eval(string)

string = "[[1, 2, 3],[4, 5, 6]]"
my_list = string_to_list(string)
print(my_list)  # [[1, 2, 3], [4, 5, 6]]

14. 매개변수 이름을 활용하여 사소한 실수 줄이기

아래와 같이 subtract라는 함수를 만들어서 사용하는 데, 함수 안에 넣어줄 인수의 순서가 바뀌면 괜히 실수가 날 수 있다.

1
2
3
4
5
def subtract(a, b):
    return a - b

print((subtract(1, 3)))  # -2
print((subtract(3, 1)))  # 2

아래와 같이 매개변수 이름을 정확히 적어서 실수를 줄이자.

1
2
3
4
5
6
def subtract(a, b):
    return a - b


print((subtract(a=1, b=3)))  # -2
print((subtract(b=3, a=1)))  # -2

15. print 한 줄로 처리하기

1
print(1, 2, 3, "a", "z", "this is here", "here is something else")

16. print 여러 줄로 처리하더라도 한 줄에 출력되도록

end 파라미터를 사용하면 된다.

1
2
3
4
5
6
print("Hello", end="")
print("World")  # HelloWorld
print("Hello", end=" ")
print("World")  # Hello World
print('words',   'with', 'commas', 'in', 'between', sep=', ')
# words, with, commas, in, between

17. print 여러 개 출력할 때 사용자 정의 구분자 sep

sep 파라미터를 사용하면 더 예쁘게 출력할 수 있다.

1
2
print("29", "01", "2022", sep="/")  # 29/01/2022
print("name", "domain.com", sep="@")  # name@domain.com

18. 파이썬 변수명 맨 앞에 숫자는 올 수 없음

1
2
four_letters = abcd # this works
4_letters = abcd # this doesn’t work

19. 파이썬 변수명 맨 앞에 연산자가 올 수 없음

1
+variable = abcd  # this doesn’t work

20. 숫자 맨 앞 자리는 0이 될 수 없음 ⭐

1
number = 0110 # this doesn't work

만약 문자열로 “0110” 같은 형식의 숫자를 만들고 싶다면 zfill 메서드를 활용하면 된다.

21. 언더스코어 “_”는 변수명 어디에도 사용할 수 있음

1
2
a______b = "abcd"  # this works
_a_b_c_d = "abcd"  # this also works

22. 자리수가 큰 숫자는 언더스코어 “_”를 사용하여 읽기 편하게 처리하기

숫자 사이에 언더스코어 _ 1개가 들어오는 건 무시된다. (자리수 구분, 가독성을 위해 자유롭게 사용할 수 있다는 뜻)

1
2
3
4
5
6
print(1_000_000_000)  # 1000000000
print(1_234_567)  # 1234567

a = 1_000_000
b = 3_000
print(a + b)  # 1003000

23. 리스트 순서 뒤집기

1
2
3
4
5
my_list = ['a', 'b', 'c', 'd']

my_list.reverse()

print(my_list)  # ['d', 'c', 'b', 'a']

24. 문자열 건너뛰어 슬라이싱

1
2
3
4
5
6
7
my_string = "This is just a sentence"
print(my_string[0:5])  # This

# Take N steps forward
print(my_string[0:10:1])  # This is ju
print(my_string[0:10:2])  # Ti sj
print(my_string[0:10:3])  # Tssu

25. 문자열 순서 뒤집어서 슬라이싱

1
2
3
4
5
6
7
my_string = "This is just a sentence"
print(my_string[10:0:-1])  # suj si sih

# Take N steps forward
print(my_string[10:0:-1])  # suj si sih
print(my_string[10:0:-2])  # sjs i
print(my_string[10:0:-3])  # s  h

26. 슬라이싱 할 때 시작/끝 인덱스는 생략 가능

1
2
3
4
my_string = "This is just a sentence"
print(my_string[4:])  # is just a sentence

print(my_string[:3])  # Thi

27. 나누기 후 소수점 이하 버리기

1
2
print(3/2)  # 1.5
print(3//2)  # 1

28. ==is 의 차이

==는 이 두 개체가 가진 값이 일치하는지 비교하는 반면, is는 두 변수가 메모리의 동일한 객체를 가리키는지 확인한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
first_list = [1, 2, 3]
second_list = [1, 2, 3]

# ==는 값이 같은지 확인
print(first_list == second_list)  # True

# is는 메모리 내의 동일한 객체를 가리키는지 확인
print(first_list is second_list)  
# False

third_list = first_list

print(third_list is first_list)  
# True

실제로 변수의 id를 확인해보면 first_list와 third_list는 동일한 ID를 갖고 있지만, second_list의 id는 다르다는 걸 확인할 수 있다.

1
2
3
print(id(first_list))
print(id(second_list))
print(id(third_list))

29. 딕셔너리 쉽게 병합하기 ⭐

1
2
3
4
5
6
dictionary_one = {"a": 1, "b": 2}
dictionary_two = {"c": 3, "d": 4}

merged = {dictionary_one, dictionary_two}

print(merged)  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

30. 부등호 연산자를 사용하여 문자열 비교하기

문자열에 부등호를 사용하면, 해당 문자열을 ascii 숫자로 변환해서 맨 앞의 문자부터 비교한다.

1
2
3
4
5
first = "abc"
second = "def"
print(first < second)  # True
second = "ab"
print(first < second)  # False

아스키코드표를 따르면, 혹은 ord함수를 이용하면 이렇게 몇 번째 유니코드 정수 값을 구할 수 있다. (39번 참고)

1
2
print(ord('a'))  # 97
print(ord('z'))  # 122

31. 문자열이 특정 문자로 시작하는지 확인하기 ⭐

인덱싱 하지 않고 startswith로 처리하는 방법.

1
2
my_string = "abcdef"
print(my_string.startswith("b"))  # False

32. id()를 사용하여 변수의 고유 ID 찾기

1
2
3
print(id(1))  # 4325776624
print(id(2))  # 4325776656
print(id("string"))  # 4327978288

33. 정수, 실수, 문자열, 불리언, 튜플은 수정 불가(immutable)

정수, 부동소수점, 문자열, 부울, 튜플처럼 수정 불가(immutable)한 객체에 변수를 할당하면 이 변수는 메모리의 객체를 가리킨다.

그래서 만약 해당 변수에 다른 값을 할당하는 경우 원래의 객체는 여전히 메모리에 있지만 이를 가리키는 변수는 손실된다.

1
2
3
4
5
6
7
number = 1
print(id(number))  # 4325215472
print(id(1))  # 4325215472

number = 3
print(id(number))  # 4325215536
print(id(1))  # 4325215472

34. 문자열과 튜플은 수정 불가 (immutable)

바로 위에서 언급한 내용이지만 너무나 중요한 내용이기 때문에 다시 한 번 강조한다…?

1
2
3
4
5
6
7
8
9
name = "Fatos"
print(id(name))  # 4422282544
name = "fatos"
print(id(name))  # 4422346608

my_tuple = (1, 2, 3, 4)
print(id(my_tuple))  # 4499290128
my_tuple = ('a', 'b')
print(id(my_tuple))  # 4498867584

35. 리스트, 집합, 딕셔너리는 수정 가능(mutable)

이는 바인딩된 객체를 잃지 않고도 해당 변수를 변경할 수 있음을 의미한다.

1
2
3
4
5
6
7
8
9
cities = ["Munich", "Zurich", "London"]
print(id(cities))  # 4482699712
cities.append("Berlin")
print(id(cities))  # 4482699712

my_set = {1, 2, 3, 4}
print(id(my_set))  # 4352726176
my_set.add(5)
print(id(my_set))  # 4352726176

36. set을 수정 불가(immutable)하도록 변경하기

frozenset을 사용하면 immutable하도록 바꿀 수 있다.

1
2
my_set = frozenset(['a', 'b', 'c', 'd'])
my_set.add("a")    # AttributeError: 'frozenset' object has no attribute 'add'

37. if-elif 블록 끝에 else는 생략 가능

그러나 elifif 없이는 단독으로 쓰일 수 없다.

1
2
3
4
5
6
7
8
9
10
def check_number(number):
    if number > 0:
        return "Positive"
    elif number == 0:
        return "Zero"

    return "Negative"


print(check_number(1))  # Positive

38. sorted()를 사용하여 2개의 문자열이 어구전철인지 확인

어구전철(語句轉綴) 또는 애너그램(anagram)은 단어나 문장을 구성하고 있는 문자의 순서를 바꾼 거다.

구성하는 문자가 순서 상관 없이 일치하는지 확인하는 방법.

1
2
3
4
5
6
7
def check_if_anagram(first_word, second_word):
    first_word = first_word.lower()
    second_word = second_word.lower()
    return sorted(first_word) == sorted(second_word)
print(check_if_anagram("testinG", "Testing"))  # True
print(check_if_anagram("Here", "Rehe"))  # True
print(check_if_anagram("Know", "Now"))  # False

39. 문자에 해당하는 유니코드 값 얻기

ord는 해당 문자에 해당하는 유니코드 정수를 반환한다.

1
2
3
4
print(ord("A"))  # 65
print(ord("B"))  # 66
print(ord("C"))  # 66
print(ord("a"))  # 97

40. 딕셔너리 key만 가져오기

1
2
3
4
5
dictionary = {"a": 1, "b": 2, "c": 3}

keys = dictionary.keys()

print(list(keys))  # ['a', 'b', 'c']

41. 딕셔너리 value만 가져오기

1
2
3
4
5
dictionary = {"a": 1, "b": 2, "c": 3}

values = dictionary.values()

print(list(values))  # [1, 2, 3]

42. 딕셔너리에서 key, value 바꿔치기

리스트 컴프리헨션을 사용하면 간단히 처리할 수 있다.

1
2
3
4
5
dictionary = {"a": 1, "b": 2, "c": 3}

reversed_dictionary = {j: i for i, j in dictionary.items()}

print(reversed)  # {1: 'a', 2: 'b', 3: 'c'}

43. boolean 값을 숫자 1 또는 0으로 변환하기

1
2
3
4
5
print(int(True))  # 0
print(int(False))  # 0

print(float(True))  # 1.0
print(float(False))  # 0.0

44. boolean 값을 산술 연산에 사용하기

True는 1, False는 0이니까…

1
2
3
4
x = 10
y = 12
result = (x - False)/(y * True)
print(result)  # 0.8333333333333334

45. 모든 자료형은 boolean으로 표현 가능

1
2
3
4
5
6
7
8
9
print(bool(3))  # True
print(bool(.0))  # False

print(bool([1,2,3]))  # True
print(bool([]))  # False

print(bool("string"))  # True
print(bool(""))  # False
print(bool(" "))  # True

46. 복소수, 2진수/8진수/16진수 표현하기

복소수 변환은 complex() 함수를 사용한다.

1
print(complex(10, 2))  # (10+2j)

이 외에도 bin() , oct()hex() 함수를 사용하면 숫자를 각각 2진수, 8진수, 16진수 형태의 문자열로 변환할 수 있다.

1
2
3
print(bin(11))  # 0b1011
print(oct(11))  # 0o13
print(hex(11))  # 0xb

파이썬에서는 기본적으로 10진수 형태로 숫자를 표현하기 때문에 다른 진수의 형태로 숫자를 표현하려면 다음과 같이 숫자 앞에 접두어를 붙여준다.

  • 2진수: 0b
  • 8진수: 0o
  • 16진수: 0x

47. 리스트 맨 앞에 요소 추가하기

리스트에 append()를 사용하면 맨 마지막에 해당 값를 추가한다. 만약 원하는 위치에 요소를 추가하고 싶다면 insert()를 사용하면 된다. (인덱스, 삽입할 요소 순으로 작성)

1
2
3
4
5
my_list = [3, 4, 5]

my_list.append(6)
my_list.insert(0, 2)
print(my_list)  # [2, 3, 4, 5, 6]

48. lambda 함수는 반드시 한 줄로 작성

lambda 함수는 한 줄로만 작성해야 한다.

여러 줄로 작성하면 SyntaxError 에러가 날 거다.

1
2
3
4
comparison = lambda x: if x > 3:
                    print("x > 3")
                else:
                    print("x is not greater than 3")

49. lambda 함수의 조건문에는 반드시 else를 포함하기

lambda 함수에 if 조건문을 이런 식으로 작성하면 SyntaxError 에러가 난다. (람다 자체의 문제가 아니라 조건문의 특성이다.)

1
comparison = lambda x: "x > 3" if x > 3

50. filter()를 사용하여 새로운 객체 돌려받기 ⭐

filter()는 lambda 함수와 조합하여 사용할 수 있다.

1
2
3
4
5
6
my_list = [1, 2, 3, 4]

odd = filter(lambda x: x % 2 == 1, my_list)

print(list(odd))   # [1, 3]
print(my_list)  # [1, 2, 3, 4]

51. map()을 사용하여 새로운 객체 돌려받기

1
2
3
4
5
6
my_list = [1, 2, 3, 4]

squared = map(lambda x: x  2, my_list)

print(list(squared))   # [1, 4, 9, 16]
print(my_list)  # [1, 2, 3, 4]

52. range()에서 사용할 수 있는 매개변수 step

1
2
3
for number in range(1, 10, 3):
    print(number, end=" ")
# 1 4 7

53. range()는 기본적으로 0부터 시작하므로 생략

그래서 0부터 시작할 거면 0을 그냥 생략하면 된다.

1
2
3
4
5
6
7
8
9
10
def range_with_zero(number):
    for i in range(0, number):
        print(i, end=' ')

def range_with_no_zero(number):
    for i in range(number):
        print(i, end=' ')

range_with_zero(3)  # 0 1 2
range_with_no_zero(3)  # 0 1 2

54. 자료형의 길이 len()는 0과 비교할 필요가 없음

길이가 0보다 크면 기본적으로 True이므로 0과 비교할 필요가 없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
def get_element_with_comparison(my_list):
    if len(my_list) > 0:
        return my_list[0]

def get_first_element(my_list):
    if len(my_list):
        return my_list[0]

elements = [1, 2, 3, 4]
first_result = get_element_with_comparison(elements)
second_result = get_element_with_comparison(elements)

print(first_result == second_result)  # True

55. 동일한 scope 내에서 동일한 이름의 함수를 여러 개 정의할 수 있음

그러나 가장 마지막에 작성된 함수가 우선하기 때문에 마지막 항목만 호출된다.

1
2
3
4
5
6
7
8
9
10
def get_address():
    return "First address"

def get_address():
    return "Second address"

def get_address():
    return "Third address"

print(get_address())  # Third address

56. scope 밖에서 해당 속성에 접근하기

1
2
3
4
5
6
7
class Engineer:
    def __init__(self, name):
        self.name = name
        self.__starting_salary = 62000

dain = Engineer('Dain')
print(dain._Engineer__starting_salary)  # 62000

57. 특정 개체의 메모리 사용량 확인하기

1
2
3
import sys

print(sys.getsizeof("bitcoin"))  # 56

58. 함수를 정의할 때 매개변수의 개수 제한 없애기

*을 사용한다.

1
2
3
4
5
6
7
8
9
def get_sum(*arguments):
    result = 0
    for i in arguments:
        result += i
    return result

print(get_sum(1, 2, 3))  # 6
print(get_sum(1, 2, 3, 4, 5))  # 15
print(get_sum(1, 2, 3, 4, 5, 6, 7))  # 28

59. super() 또는 클래스 이름을 사용하여 부모클래스의 생성자를 호출하기

super()를 사용하여 부모클래스 이니셜라이저 호출하기

1
2
3
4
5
6
7
8
9
10
11
12
class Parent:
    def __init__(self, city, address):
        self.city = city
        self.address = address

class Child(Parent):
    def __init__(self, city, address, university):
        super().__init__(city, address)
        self.university = university

child = Child('Zürich', 'Rämistrasse 101', 'ETH Zürich')
print(child.university)  # ETH Zürich

부모클래스의 이름을 사용하여 이니셜라이저 호출하기

1
2
3
4
5
6
7
8
9
10
11
12
class Parent:
    def __init__(self, city, address):
        self.city = city
        self.address = address

class Child(Parent):
    def __init__(self, city, address, university):
        Parent.__init__(self, city, address)
        self.university = university

child = Child('Zürich', 'Rämistrasse 101', 'ETH Zürich')
print(child.university)  # ETH Zürich

__init__() 및 super()를 사용하는 부모 이니셜라이저에 대한 호출은 자식 클래스의 이니셜라이저 내에서만 사용할 수 있다.

60. 클래스 내에서 + 연산자 재정의하기

+__add__()함수를 통해 재정의 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Expenses:
    def __init__(self, rent, groceries):
        self.rent = rent
        self.groceries = groceries

    def __add__(self, other):
        return Expenses(self.rent + other.rent,
                        self.groceries + other.groceries)


april_expenses = Expenses(1000, 200)
may_expenses = Expenses(1000, 300)

total_expenses = april_expenses + may_expenses
print(total_expenses.rent)  # 2000
print(total_expenses.groceries)  # 500

61. 클래스 내에서 <, == 등의 연산자 재정의하기

부등호 <__lt__()를 재정의 하면 된다.

1
2
3
4
5
6
7
8
9
10
11
class Game:
    def __init__(self, score):
        self.score = score

    def __lt__(self, other):
        return self.score < other.score

first = Game(1)
second = Game(2)

print(first < second)  # True

==__eq__()를 재정의하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Journey:
    def __init__(self, location, destination, duration):
        self.location = location
        self.destination = destination
        self.duration = duration

    def __eq__(self, other):
        return ((self.location == other.location) and
                (self.destination == other.destination) and
                (self.duration == other.duration))

first = Journey('Location A', 'Destination A', '30min')
second = Journey('Location B', 'Destination B', '30min')

print(first == second)

클래스 내에서 연산자를 재정의하기 위해서는 아래와 같은 함수를 다뤄주면 된다.

  • + : __add__()
  • – : __sub__()
  • * : __mul__()
  • / : __truediv__()
  • == : __eq__()
  • != : __ne__()
  •  : __gt__()

  • < : __lt__()
  • = : __ge__()

  • <= : __le__()

62. 클래스 내에서 개체에 대한 print 표현형을 사용자 정의하기

클래스 내에서 __repr__()를 조작하면 print를 통해 출력했을 때 어떻게 표현할지 직접 정의할 수 있다.

1
2
3
4
5
6
7
8
9
class Rectangle:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return repr('Rectangle with area=' + str(self.a * self.b))

print(Rectangle(3, 4))  # 'Rectangle with area=12'

63. 문자열 대문자/소문자 바꾸기

문자열에 대해 swapcase()를 사용하면 대문자/소문자를 바꿔준다.

1
2
3
string = "This is just a sentence."
result = string.swapcase()
print(result)  # tHIS IS JUST A SENTENCE.

64. 문자열이 공백인지 확인하기

문자열에 대해 isspace()를 사용하면 모든 문자가 공백문자인지 확인한다.

1
2
3
4
5
6
7
string = "     "
result = string.isspace()
print(result)  # True

string = ""
result = string.isspace()
print(result)  # False

65. 문자열의 모든 문자가 알파벳 또는 숫자인지 확인하기

문자열에 대해 isalnum()을 사용하면 모든 문자가 알파벳과 숫자로만 이루어져있는지 확인한다.

1
2
3
4
5
6
7
8
9
10
11
name = "Password"
print(name.isalnum())  # True, because all characters are alphabets

name = "Secure Password "
print(name.isalnum())  # False, because it contains whitespaces

name = "S3cur3P4ssw0rd"
print(name.isalnum())  # True

name = "133"
print(name.isalnum())  # True, because all characters are numbers

66. 문자열의 모든 문자가 알파벳인지 확인하기

문자열에 대해 isalpha()를 사용하면 모든 문자가 알파벳으로만 이루어져있는지 확인한다.

1
2
3
4
5
6
7
8
string = "Name"
print(string.isalpha())  # True

string = "Firstname Lastname"
print(string.isalpha())  # False, because it contains whitespace

string = P4ssw0rd
print(string.isalpha())  # False, because it contains numbers

67. 문자열 양쪽에서 특정 문자 제거하기

문자열에 대해 strip([chars]), lstrip([chars]), rstrip([chars])과 같은 함수를 사용할 때 인자로 문자열을 넣어주면 해당 문자를 처음과 끝에서 찾아 제거한다. 그냥 strip은 양쪽에서, l은 왼쪽, r은 오른쪽에서 찾아 제거.

1
2
3
4
5
6
7
8
string = "This is a sentence with       "
print(string.rstrip())  # "This is a sentence with"

string = "this here is a sentence…..,,,,aaaaasd"
print(string.rstrip(".,dsa"))  # "this here is a sentence"

string = "ffffffffFirst"
print(string.lstrip("f"))  # First

68. 문자열이 숫자 형식인지 확인하기 ⭐

문자열에 isdigit()을 사용하면 해당 문자열이 숫자 형식인지 확인한다.

1
2
3
4
5
6
7
8
9
10
11
string = "seven"
print(string.isdigit())  # False

string = "1337"
print(string.isdigit())  # True

string = "5a"
print(string.isdigit())  # False, because it contains the character 'a'

string = "25"
print(string.isdigit())  # False

69. 문자열이 중국어로 숫자인지 확인하기

문자열에 isnumeric()을 사용하면 숫자 표현에 해당하는 문자열인지 확인한다.

중국어뿐만 아니라 제곱근, 분수, 거듭제곱 등의 특수문자가 있더라도 isnumeric() 함수는 True를 반환한다.

1
2
3
4
5
# 42673 in Arabic numerals
string = "四二六七三"

print(string.isdigit())  # False
print(string.isnumeric())  # True

70. 문자열의 모든 단어 첫 글자가 대문자인지 확인하기

문자열에 istitle()을 사용하면 영어에서 제목을 표현할 때처럼 모든 단어 첫 글자가 문자열인지 확인한다.

1
2
3
4
5
6
7
8
9
10
11
string = "This is a sentence"
print(string.istitle())  # False

string = "10 Python Tips"
print(string.istitle())  # True

string = "How to Print A String in Python"
print(string.istitle())  # False, because of the first characters being lowercase in "to" and "in"

string = "PYTHON"
print(string.istitle())  # False. It's titlelized version is "Python"

71. 튜플에 음수 인덱스 사용 가능

1
2
3
4
numbers = (1, 2, 3, 4)

print(numbers[-1])  # 4
print(numbers[-4])  # 1

72. 튜플 내부에 리스트와 튜플 둘 다 담는 것도 가능

1
2
3
4
mixed_tuple = (("a"*10, 3, 4), ['first', 'second', 'third'])

print(mixed_tuple[1])  # ['first', 'second', 'third']
print(mixed_tuple[0])  # ('aaaaaaaaaa', 3, 4)

73. 리스트에 조건을 만족하는 요소가 있는지 카운트 하기

리스트에 count()를 사용하면 빠르게 해당 요소가 몇 개 있는지 확인할 수 있다.

1
2
3
names = ["Besim", "Albert", "Besim", "Fisnik", "Meriton"]

print(names.count("Besim"))  # 2

74. slice()를 사용하여 마지막 n개의 요소 슬라이싱하기

인덱싱을 하는 것과 다르다.

1
2
3
4
5
6
7
8
9
10
11
12
13
my_list = [1, 2, 3, 4, 5, 6]
slicing = slice(-3, None)

# Getting the last 3 elements from the list
print(my_list[slicing])  # [4, 5, 6]
# Getting only the third element starting from the right
print(my_list[-3])  # 4

string = "Data Science"
# start = 1, stop = None (don't stop anywhere), step = 1
# contains 1, 3 and 5 indices
slice_object = slice(5, None)
print(string[slice_object])   # Science

75. 튜플에 조건을 만족하는 요소가 있는지 카운트 하기

튜플에 count()를 사용하면 빠르게 해당 요소가 몇 개 있는지 확인할 수 있다. (73번과 같은 내용인데 굳이…?)

1
2
3
my_tuple = ('a', 1, 'f', 'a', 5, 'a')

print(my_tuple.count('a'))  # 3

76. 튜플에서 특정 요소의 인덱스 추출하기

튜플에 index()를 사용하면 빠르게 해당 요소가 몇 번째에 위치했는지 인덱스를 확인할 수 있다.

1
2
my_tuple = ('a', 1, 'f', 'a', 5, 'a')
print(my_tuple.index('f'))  #  2

77. 튜플에서 특정 간격으로 건너뛰어 요소 추출하기

1
2
my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(my_tuple[::3])  # (1, 4, 7, 10)

78. 튜플에서 특정 인덱스부터 끝까지 요소 추출하기

1
2
my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(my_tuple[3:])  # (4, 5, 6, 7, 8, 9, 10)

79. 리스트, 집합, 딕셔너리에서 모든 요소 제거하기

clear()를 사용하면 된다.

1
2
3
4
5
6
7
8
9
10
11
my_list = [1, 2, 3, 4]
my_list.clear()
print(my_list)  # []

my_set = {1, 2, 3}
my_set.clear()
print(my_set)  # set()

my_dict = {"a": 1, "b": 2}
my_dict.clear()
print(my_dict)  # {}

80. 두 개의 집합 합치기 (합집합 구하기)

union()을 사용하면 된다.

1
2
3
4
first_set = {1, 4, 5, 6}
second_set = {1, 2, 3, 7}

print(first_set.union(second_set))  # {1, 2, 3, 4, 5, 6, 7}

아니면 두 번째 집합의 요소를 첫 번째 집합에 삽입하는 update()를 사용할 수도 있다.

1
2
3
4
5
first_set = {1, 4, 5, 6}
second_set = {1, 2, 3, 7}

first_set.update(second_set)
print(first_set)  # {1, 2, 3, 4, 5, 6, 7}

81. print문 안에 if 조건문 사용하기 ⭐

1
2
3
4
5
def is_positive(number):
    print("Positive" if number > 0 else "Negative")  # Positive

is_positive(-3) # Negative
is_positive(4)  # Positive

82. 하나의 if 안에서 모든 조건을 만족하는지 확인하기 ⭐

리스트 안에 검사할 조건을 다 넣어두고, all()을 사용하는 방식. 처음 알았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
math_points = 51
biology_points = 78
physics_points = 56
history_points = 72

my_conditions = [
    math_points > 50, 
    biology_points > 50,
    physics_points > 50, 
    history_points > 50
    ]

if all(my_conditions):
    print("Congratulations! You have passed all of the exams.")
else:
    print("I am sorry, but it seems that you have to repeat at least one exam.")
    
# Congratulations! You have passed all of the exams.

83. 하나의 if 안에서 여러 조건 중 하나라도 만족하는지 확인하기⭐

리스트 안에 검사할 조건을 다 넣어두고, any()를 사용하는 방식. 이것도 처음 알았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
math_points = 41
biology_points = 58
physics_points = 36
history_points = 42

my_conditions = [
    math_points > 50, 
    biology_points > 50,
    physics_points > 50, 
    history_points > 50
    ]

if any(my_conditions):
    print("Congratulations! You have passed all of the exams.")
else:
    print("I am sorry, but it seems that you have to repeat at least one exam.")

# Congratulations! You have passed all of the exams.

84. 비어있지 않은 모든 문자열은 True

1
2
3
print(bool("Non empty"))  # True
print(bool(" "))  # True
print(bool(""))  # False

85. 비어있지 않은 모든 리스트, 튜플, 딕셔너리는 True

1
2
3
4
print(bool([]))  # False
print(bool(set([])))  # False
print(bool({}))  # False
print(bool({"a": 1}))  # True

86. None, False, 0은 False

1
2
3
4
print(bool(False))  # False
print(bool(None))  # False
print(bool(0))  # False
print(bool("False"))  # True

87. 함수 내에서는 전역 변수의 값을 변경할 수 없음

1
2
3
4
5
6
7
8
string = "string"

def do_nothing():
  string = "inside a method"

do_nothing()

print(string)  # string

만약 함수 내에서 전역 변수에 접근하고 싶다면 global을 사용해야 한다.

1
2
3
4
5
6
7
8
9
string = "string"

def do_nothing():
    global string
    string = "inside a method"

do_nothing()

print(string)  # inside a method

88. collectionsCounter를 사용해 문자열이나 리스트에서 요소 개수 카운트 하기 ⭐

Counter()는 정말 유용하다.

1
2
3
4
5
6
7
from collections import Counter

result = Counter("Banana")
print(result)  # Counter({'a': 3, 'n': 2, 'B': 1})

result = Counter([1, 2, 1, 3, 1, 4, 1, 5, 1, 6])
print(result)  # Counter({1: 5, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1})

89. collectionsCounter를 사용해 두 문자열이 애너그램인지 확인하기

어구전철(語句轉綴) 또는 애너그램(anagram)은 단어나 문장을 구성하고 있는 문자의 순서를 바꾼 것.

Counter()를 사용해서 확인할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
from collections import Counter

def check_if_anagram(first_string, second_string):
    first_string = first_string.lower()
    second_string = second_string.lower()
    return Counter(first_string) == Counter(second_string)


print(check_if_anagram('testinG', 'Testing'))  # True
print(check_if_anagram('Here', 'Rehe'))  # True
print(check_if_anagram('Know', 'Now'))  # False

sorted()를 사용해서 확인하는 방법도 있다.

1
2
3
4
5
6
7
8
def check_if_anagram(first_word, second_word):
    first_word = first_word.lower()
    second_word = second_word.lower()
    return sorted(first_word) == sorted(second_word)

print(check_if_anagram("testinG", "Testing"))  # True
print(check_if_anagram("Here", "Rehe"))  # True
print(check_if_anagram("Know", "Now"))  # False

90. itertoolscount를 사용해 리스트에서 요소 개수 카운트 하기

1
2
3
4
5
6
7
8
9
10
11
12
from itertools import count

my_vowels = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']

current_counter = count()

string = "This is just a sentence."

for i in string:
    if i in my_vowels:
        print(f"Current vowel: {i}")
        print(f"Number of vowels found so far: {next(current_counter)}")

91. 문자열, 리스트의 요소를 빈도 순으로 정렬하기

기본적으로 collections.Counter()는 빈도에 따라 정렬해주진 않지만, most_common()을 사용해주면 쉽게 해결된다.

1
2
3
4
5
from collections import Counter

result = Counter([1, 2, 3, 2, 2, 2, 2])
print(result)  # Counter({2: 5, 1: 1, 3: 1})
print(result.most_common())  # [(2, 5), (1, 1), (3, 1)]

92. 리스트에서 가장 많은 요소 쉽게 찾기

max()와 set()을 조합하는 방법

1
2
3
my_list = ['1', 1, 0, 'a', 'b', 2, 'a', 'c', 'a']

print(max(set(my_list), key=my_list.count))  # a

93. copy()deepcopy()의 차이점

파이썬 공식 문서에는 이렇게 써있다.

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

이게 copy()의 예시

1
2
3
4
5
6
first_list = [[1, 2, 3], ['a', 'b', 'c']]
second_list = first_list.copy()
first_list[0][2] = 831

print(first_list)  # [[1, 2, 831], ['a', 'b', 'c']]
print(second_list)  # [[1, 2, 831], ['a', 'b', 'c']]

이게 deepcopy()의 예시

1
2
3
4
5
6
7
8
import copy

first_list = [[1, 2, 3], ['a', 'b', 'c']]
second_list = copy.deepcopy(first_list)
first_list[0][2] = 831

print(first_list)  # [[1, 2, 831], ['a', 'b', 'c']]
print(second_list)  # [[1, 2, 3], ['a', 'b', 'c']]

94. 딕셔너리에 존재하지 않는 키 접근할 때 오류 방지 ⭐

딕셔너리에서 존재하지 않는 키에 접근하면 KeyError 오류가 발생한다.

1
2
my_dictonary = {"name": "Name", "surname": "Surname"}
print(my_dictonary["age"])  # KeyError: 'age'

collections의 defaultdict()를 사용하면 딕셔너리 키 에러 문제를 방지할 수 있다.

1
2
3
4
5
6
7
from collections import defaultdict

my_dictonary = defaultdict(str)
my_dictonary['name'] = "Name"
my_dictonary['surname'] = "Surname"

print(my_dictonary["age"]) 

95. 직접 나만의 반복자(iterator)를 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class OddNumbers:
    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        x = self.a
        self.a += 2
        return x


odd_numbers_object = OddNumbers()
iterator = iter(odd_numbers_object)

print(next(iterator))  # 1
print(next(iterator))  # 3
print(next(iterator))  # 5

96. 리스트에서 중복 항목 제거하기

set()을 활용한다.

1
2
my_set = set([1, 2, 1, 2, 3, 4, 5])
print(list(my_set))  # [1, 2, 3, 4, 5]

97. 모듈 위치 확인/출력하기

1
2
3
import torch

print(torch)  # <module 'torch' from '/Users/...'

98. “not in”을 사용해 리스트에 있는지 확인하기

1
2
3
4
5
6
7
8
odd_numbers = [1, 3, 5, 7, 9]
even_numbers = []

for i in range(9):
    if i not in odd_numbers:
        even_numbers.append(i)

print(even_numbers)  # [0, 2, 4, 6, 8]

99. sort()와 sorted()의 차이점

sort()는 원본 목록을 정렬하는 반면, sorted()는 새로운 정렬된 목록을 반환해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
groceries = ['milk', 'bread', 'tea']

new_groceries = sorted(groceries)
# new_groceries = ['bread', 'milk', 'tea']

print(new_groceries)

# groceries = ['milk', 'bread', 'tea']
print(groceries)

groceries.sort()

# groceries = ['bread', 'milk', 'tea']
print(groceries)

100. uuid 모듈을 사용해 고유 ID 생성하기 ⭐

UUID는 Universally Unique Identifier의 약자. 한국어로 범용 고유 식별자. 이 표준에 따라 ID를 부여하면 실제 사용상에서 중복될 가능성이 거의 없다고 인정되기 때문에 많이 사용되고 있다.

파이썬 내장 모듈 uuid가 있다.

1
2
3
4
5
6
7
import uuid

# Generate a UUID from a host ID, sequence number, and the current time
print(uuid.uuid1())  # 308490b6-afe4-11eb-95f7-0c4de9a0c5af

# Generate a random UUID
print(uuid.uuid4())  # 93bc700b-253e-4081-a358-24b60591076a
This post is licensed under CC BY 4.0 by the author.