본문 바로가기
DEV/파이썬 이론

파이썬 코딩 :: 파이썬 클래스, 축약식, lambda, 계산기 만들기(2)_TIL#11

by 올커 2022. 9. 14.

■ JITHub 개발일지(TIL : Today I Learned) 11일차


 

□  TIL ::

     파이썬 클래스, 축약식, lambda, 계산기 만들기


1. 클래스

 - str 메서드(__str__) : init에서 규정한 클래스 자체 내용을 출력하고 싶을 때, 형식을 지정하는 메서드

   *인스턴스를 그냥 출력하면 주소값으로 나오는데, str을 지정해주면 지정된 형식의 값으로 출력됨

class Profile():
	def __init__(self, profile):
		self.profile = profile
  
	def __str__(self):
		return str(self.profile)

profile = Profile({
	"name" : "lee",
	"gender" : "man",
	"birthday" : "01/01",
	"age" : 32,
	"phone" : "01012341234",
	"email" : "python@sparta.com"
})

print(profile)

# __str__이 없을 경우
"""
<__main__.Profile object at 0x000001A2B53E3F10>
"""

# __str__이 있을 경우
"""
{'name': 'lee', 'gender': 'man', 'birthday': '01/01', 'age': 32, 'phone': '01012341234', 'email': 'python@sparta.com'}
"""

 

class Profile():
	def __init__(self, profile):
		self.profile = profile
  
	def __str__(self):
		return "프로필의 인스턴스 입니다!"

profile = Profile({
	"name" : "lee",
	"gender" : "man",
	"birthday" : "01/01",
	"age" : 32,
	"phone" : "01012341234",
	"email" : "python@sparta.com"
})

print(profile)
        
"""
프로필의 인스턴스 입니다!
"""

 

2. try/exception

  - 파이썬에서는 try, except 문법을 사용하여 에러가 발생했을 때 처리해줄 수 있다.

number = input()

try:
    int(number)
    10 / number

except ValueError: # int로 변환하는 과정에서 에러가 발생했을 떄
    print(f"{number}은(는) 숫자가 아닙니다.")
    
except ZeroDivisionError: # 0으로 나누면서 에러가 발생했을 때
    print("0으로는 나눌수 없습니다.")
    
except Exception as e: # 위에서 정의하지 않은 에러가 발생했을 때(권장하지 않음)
    print(f"예상하지 못한 에러가 발생했습니다. error : {e}")

# except 문법 또한 if / elif와 같이 연달아서 작성할 수 있습니다.

 

 - 아래 식을 보면 if문과 try문을 비교하고 있는데, if문의 경우 num.isdigit(): 분기문을 무조건 타지만, try except문은 에러가 발생하지 않을 경우 num = int(num)만 수행하기 때문에 양이 많을 경우 처리 속도가 상대적으로 빠르다.

# case 1
num = "abc"

if num.isdigit:
    num = int(num)
else:
    num = '-'
    
print(num)


# case 2
num = "10"
try:
    num = int(num)
except:
    num = "-"

 

 

3. stacktrace

  - stacktrace : 에러가 발생했을 때 에러가 발생 한 위치를 찾아내기 위해 호출 된 함수의 목록을 보여주고
개발자는 stacktrace를 따라가며 에러가 발생한 위치를 추적할 수 있다.

def 집까지_걸어가기():
    print(error) # 선언되지 않은 변수를 호출했기 때문에 에러 발생

def 버스_탑승():
    집까지_걸어가기()

def 환승():
    버스_탑승()

def 지하철_탑승():
    환승()

def 퇴근하기():
    지하철_탑승()

퇴근하기()

"""
Traceback (most recent call last):
  File "sample.py", line 17, in <module>
    퇴근하기()
  File "sample.py", line 15, in 퇴근하기
    지하철_탑승()
  File "sample.py", line 12, in 지하철_탑승
    환승()
  File "sample.py", line 9, in 환승
    버스_탑승()
  File "sample.py", line 5, in 버스_탑승
    집까지_걸어가기()
  File "sample.py", line 2, in 집까지_걸어가기
    print(error)
NameError: name 'error' is not defined. Did you mean: 'OSError'?

 

4. 축약식

  - 축약식의 장점 : 긴 코드를 간략하게 줄일수 있다

  - 축약식의 단점 : 남용할 경우 가독성이 떨어지고 추후 코드 관리가 힘들수 있다.
  - list, set, tuple, dict 자료형이 축약식으로 표현이 가능하며, 기본적인 구조는 동일하고, 어떤 괄호 기호를 사용하는지 / 어떤 형태로 사용하는지에 따라 저장되는 자료형이 달라진다.

 

  1) 리스트, 튜플, 셋 축약식 활용방법

# 기본적인 활용 방법
# [list에 담길 값 for 요소 in 리스트]
numbers = [x for x in range(5)] # [0, 1, 2, 3, 4]

# 조건문은 축약식 뒷부분에 작성하며, 축약식이 True인 경우 list에 값이 담긴다.
even_numbers = [x for x in range(10) if x % 2 == 0] # [0, 2, 4, 6, 8]

# 아래와 같이 활용할 수도 있다.
people = [
    ("lee", 32),
    ("kim", 23),
    ("park", 27),
    ("hong", 29),
    ("kang", 26)
]

average_age = sum([x[1] for x in people]) / len(people)
print(average_age) # 27.4

#list 축약식의 []를 ()혹은 {}로 바꿔주면 tuple, set 축약식을 사용하실수 있습니다.

  ※ 리스트 축약식을 사용하여 코드 문장 간소화 예시

people = [
	("lee", 32),
	("kim", 23),
	("park", 27),
	("hong", 29),
	("kang", 26),
]

# case 1
sum_age = 0
for i in people:
    sum_age += i[1]
average_age = sum_age / len(people)
print(average_age)

# case 2
ages = [x[1] for x in people]
sum_ages = sum(ages)
average_age = sum_ages / len(people)
print(average_age)

# case 3
average_age = sum([x[1] for x in people]) / len(people)
print(average_age)

 

  2) 딕셔너리 축약식 활용법

# dictionary 축약식의 구조는 list와 동일하지만, key / value 형태로 지정해야 합니다.
people = [
    ("lee", 32, "man"),
    ("kim", 23, "man"),
    ("park", 27, "woman"),
    ("hong", 29, "man"),
    ("kang", 26, "woman")
]

people = {name: {"age": age, "gender": gender} for name, age, gender in people}
print(people)

# result print
"""
{
    'lee': {'age': 32,
             'gender': 'man'},
    'kim': {'age': 23,
             'gender': 'man'},
    'park': {'age': 27,
             'gender': 'woman'},
    'hong': {'age': 29,
             'gender': 'man'},
    'kang': {'age': 26,
             'gender': 'woman'}
 }
"""

 

5. lambda / map / filter / sort 활용

  1) lambda

 - lambda는 다른 말로 익명 함수(anonymous function)이라고도 불리며, 보통 map, filter, sort와 함께 사용된다.

# map은 함수와 리스트를 인자로 받아 리스트의 요소들로 함수를 호출해줍니다.
string_numbers = ["1", "2", "3"]
integer_numbers = list(map(int, string_numbers))
print(integer_numbers) # [1, 2, 3]

# map 함수를 사용하지 않는 경우 아래와 같이 구현할 수 있습니다.
string_numbers = ["1", "2", "3"]
integer_numbers = []

for i in string_numbers:
    integer_numbers.append(int(i))

print(integer_numbers) # [1, 2, 3]

# list 축약식으로도 동일한 기능을 구현할 수 있습니다.
# map과 list 축약식 중 어떤걸 써야 할지 고민된다면 이 글을 읽어보시는것을 추천합니다.
string_numbers = ["1", "2", "3"]
integer_numbers = [int(x) for x in string_numbers]
print(integer_numbers) # [1, 2, 3]


# map 함수와 lambda 함수를 함께 사용하면 더 다채로운 기능을 구현할 수 있습니다.
numbers = [1, 2, 3, 4]
double_numbers = list(map(lambda x: x*2, numbers))
print(double_numbers) # [2, 4, 6, 8]


# 바로 위의 식을 축약식을 활용해서 코드를 짤 수도 있다.
numbers = [1, 2, 3, 4]
double_numbers = [x*2 for x in numbers]
print(double_numbers) # [2, 4, 6, 8]

  2) filter

# filter 함수는 map과 유사한 구조를 가지고 있으며, 조건이 참인 경우 저장합니다.
numbers = [1, 2, 3, 4, 5, 6, 7, 8]

even_numbers = list(filter(lambda x: x%2 == 0, numbers))
print(even_numbers) # [2, 4, 6, 8]

# filter 함수 또한 list 축약식으로 동일한 기능을 구현할 수 있습니다.
numbers = [1, 2, 3, 4, 5, 6, 7, 8]

even_numbers = [x for x in numbers if x%2 == 0]
print(even_numbers) # [2, 4, 6, 8]

  3) sort

# sort 함수를 사용하면 list를 순서대로 정렬할 수 있습니다.
numbers = [5, 3, 2, 4, 6, 1]
numbers.sort()
print(numbers) # [1, 2, 3, 4, 5, 6]


# 역순으로 정렬시키기
numbers = [5, 3, 2, 4, 6, 1]
numbers.sort(reverse=True)
print(numbers) # [6, 5, 4, 3, 2, 1]


# sort와 lambda 함수를 같이 사용하면 복잡한 구조의 list도 정렬할 수 있습니다.
people = [
    ("lee", 32),
    ("kim", 23),
    ("park", 27),
    ("hong", 29),
    ("kang", 26)
]

# 나이 순으로 정렬하기
people.sort(key=lambda x: x[1])
print(people)

# result print
"""
[
    ("kim", 23),
    ("kang", 26),
    ("park", 27),
    ("hong", 29),
    ("lee", 32)
]
"""

# 나이 역순으로 정렬하기
people.sort(key=lambda x: x[1], reverse=True)
print(people)


# 2개의 우선순위 기준 주기 (우선순위를 튜플로 주면 된다)
people.sort(key=lambda x: (x[0], x[1]))
print(people)


# filter가 쓰인 문을 축약식 + if문을 사용하여 간소화하기
people = [x for x in people if x[1] >= 30]
print(people)

 

 

 

6. 계산기 만들기

 - 조건 추가

  • 클래스를 활용해 작성했던 계산기 코드를 활용해주세요
  • 기존처럼 사용자의 입력을 받고 출력하되, try / except를 활용해 사용자의 입력을 검증하는 코드를 추가해주세요
    • 두 번쨰 숫자에 0을 입력하고 나누기를 시도할 경우 “0으로 나눌 수 없습니다” 문구를 출력해주세요
    • 숫자가 아닌 다른 값을 입력했을 경우 “숫자만 입력 가능합니다” 라는 문구를 출력해 주세요
# 계산기 만들어보기(with class)
class Calc:
    # def __init__(self, a, b):
    #     self.a = a
    #     self.b = b

    def set_number(self, a, b):
        self.a = a
        self.b = b
        
    def plus(self):
        result = self.a + self.b
        return result

    def minus(self):
        result = self.a - self.b
        return result
    
    def multiple(self):
        result = self.a * self.b
        return result
    
    def divide(self):
        result = self.a / self.b
        return result


# try except문 안에는 에러가 발생할 수 있는 코드만 들어가도록 하는 것이 좋다.
try:
    calc = Calc()
    a, b = map(int, input().split())
    calc.set_number(a, b)
    
    print(calc.plus()) # 더한 값
    print(calc.minus()) # 뺀 값
    print(calc.multiple()) # 곱한 값
    print(calc.divide()) # 나눈 값
    
# Data validation : 데이터 유효성 검사
except ValueError: # int로 변환하는 과정에서 에러가 발생했을 때
    print("숫자만 입력 가능합니다.")
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")

 

7. 유저 관리 및 내용 출력

  - 조건

  • filter 혹은 리스트 축약식을 사용해 코드를 작성해주세요
  • 제공 된 사용자들 중 나이가 20살 미만인 사람들은 제외해주세요
  • 사용자들을 나이 순으로 정렬해주세요
from pprint import pprint

people = [
    ("Blake Howell", "Jamaica", 18, "aw@jul.bw"),
    ("Peter Bowen", "Burundi", 30, "vinaf@rilkov.il"),
    ("Winnie Hall", "Palestinian Territories", 22, "moci@pacivhe.net"),
    ("Alfred Schwartz", "Syria", 29, "ic@tolseuc.pr"),
    ("Carrie Palmer", "Mauritius", 28, "fenlofi@tor.aq"),
    ("Rose Tyler", "Martinique", 17, "as@forebjab.et"),
    ("Katharine Little", "Anguilla", 29, "am@kifez.et"),
    ("Brent Peterson", "Svalbard & Jan Mayen", 22, "le@wekciga.lr"),
    ("Lydia Thornton", "Puerto Rico", 19, "lefvoru@itbewuk.at"),
    ("Richard Newton", "Pitcairn Islands", 17, "da@lasowiwa.su"),
    ("Eric Townsend", "Svalbard & Jan Mayen", 22, "jijer@cipzo.gp"),
    ("Trevor Hines", "Dominican Republic", 15, "ev@hivew.tm"),
    ("Inez Little", "Namibia", 26, "meewi@mirha.ye"),
    ("Lloyd Aguilar", "Swaziland", 16, "oza@emneme.bb"),
    ("Erik Lane", "Turkey", 30, "efumazza@va.hn"),
]

people = [x for x in people if x[2] >= 20]
people.sort(key=lambda x: x[2])
pprint(people)

"""
[('Winnie Hall', 'Palestinian Territories', 22, 'moci@pacivhe.net'),
 ('Brent Peterson', 'Svalbard & Jan Mayen', 22, 'le@wekciga.lr'),
 ('Eric Townsend', 'Svalbard & Jan Mayen', 22, 'jijer@cipzo.gp'),
 ('Inez Little', 'Namibia', 26, 'meewi@mirha.ye'),
 ('Carrie Palmer', 'Mauritius', 28, 'fenlofi@tor.aq'),
 ('Alfred Schwartz', 'Syria', 29, 'ic@tolseuc.pr'),
 ('Katharine Little', 'Anguilla', 29, 'am@kifez.et'),
 ('Peter Bowen', 'Burundi', 30, 'vinaf@rilkov.il'),
 ('Erik Lane', 'Turkey', 30, 'efumazza@va.hn')]
"""

 

 


■ TIT :: Today I thought

 - 파이썬 문법을 배우면서 점점 복잡해짐을 느끼고 있다. 다양한 용법이 나오고 있는데 그날그날 익히지 않으면 금방 잊혀질까 두려울 정도이다. 정리해둔 내용들을 꼼꼼히 다시 하나하나 정리해볼 필요가 있겠다.

 - 지난주에 정리하지 못했던 깃에 대한 내용을 주로 확인했다. 로컬 저장소(repo)에서 git bash를 활용하여 작업하는 것을 주로 정리하고 있다. 소스트리를 사용해도 좋지만 CLI 환경에서 모든 기능을 사용할 수 있다고 하니, 개념만 꽉 잡고 CLI 환경에서 작업하는 것을 더 익숙하게 만드는 것을 목표로 해야겠다.

 - 금일은 백준 문제 풀이를 할 시간이 없었다.. 지난주에 git을 정리하지 못했던 것이 가장 컸다.

 - 백준 문제, 그리고 자료구조와 알고리즘에서 앞으로 갈수록 깊은 내용을 공부해볼 예정이다. 각오 단단히 하자

반응형

댓글