함수는 특정 작업을 수행하는 코드 블록입니다. 재사용 가능하게 만들어져서 여러 번 호출할 수 있습니다.
개념
정의: 함수를 정의할 때는 def 키워드를 사용합니다.
호출: 정의한 함수를 호출하여 실행할 수 있습니다.
매개변수: 함수에 값을 전달할 수 있는 변수를 매개변수라고 합니다.
반환값: 함수가 작업을 수행한 후 반환할 수 있는 값을 반환값이라고 합니다.
예제
# 함수 정의
def greet(name):
return f"Hello, {name}!"
# 함수 호출
message = greet("Alice")
print(message) # 출력: Hello, Alice!
04-2 사용자 입력
사용자로부터 데이터를 입력받는 방법입니다. 보통 input() 함수를 사용합니다.
개념
입력 받기: input() 함수를 사용하여 사용자로부터 입력을 받습니다.
형변환: 입력받은 데이터는 문자열로 취급되므로, 필요에 따라 다른 형으로 변환할 수 있습니다.
예제
# 사용자로부터 이름 입력 받기
name = input("Enter your name: ")
print(f"Hello, {name}!")
04-3 파일 읽고 쓰기
파일을 읽고 쓰는 방법입니다. 파일을 열고, 읽고, 쓰고, 닫는 과정으로 이루어집니다.
개념
파일 열기: open() 함수를 사용하여 파일을 엽니다.
읽기/쓰기: read(), write() 메서드를 사용하여 파일을 읽고 씁니다.
파일 닫기: close() 메서드를 사용하여 파일을 닫습니다.
예제
# 파일에 쓰기
with open('example.txt', 'w') as file:
file.write("Hello, World!")
# 파일 읽기
with open('example.txt', 'r') as file:
content = file.read()
print(content) # 출력: Hello, World!
04-4 프로그램의 입출력
프로그램의 입출력은 콘솔을 통한 데이터 입력과 출력입니다.
개념
입력: input() 함수를 통해 데이터를 입력받습니다.
출력: print() 함수를 통해 데이터를 출력합니다.
예제
# 사용자로부터 두 수를 입력받아 더하기
num1 = int(input("Enter first number: "))
num2 = int(input("Enter second number: "))
result = num1 + num2
print(f"The sum is: {result}")
이 예제들은 각각의 개념을 쉽게 이해하고 활용할 수 있도록 돕는 간단한 코드들입니다. 이를 통해 초심자들도 각 기능을 체험하고 실습할 수 있습니다.
자료형 강의 중 다소 혼동이 있었던 개념에 대해 정리하였습니다. 나머지 내용은 점프투파이썬 위키독스를 참고하세요. https://wikidocs.net/11
임뮤터블 변수 (Immutable Variables) VS 뮤터블 변수 (Mutable Variables)
1. 임뮤터블 변수 (Immutable Variables)
임뮤터블 변수는 값이 한 번 정해지면 변경할 수 없는 변수입니다. 즉, 한 번 생성된 값은 수정할 수 없습니다. 대표적인 임뮤터블 변수 타입에는 다음이 있습니다:
숫자 (int, float): 숫자형 변수는 생성된 이후에 그 값을 변경할 수 없습니다.
문자열 (str): 문자열도 생성된 후에 개별 문자나 전체 문자열을 변경할 수 없습니다.
튜플 (tuple): 튜플은 리스트와 비슷하지만, 한 번 생성되면 그 안의 값들을 변경할 수 없습니다.
임뮤터블 변수는 값이 변경될 수 없으므로, 변수의 값을 변경하려고 하면 새로운 메모리 주소에 새로운 값을 할당하게 됩니다. 예를 들어 봅시다:
# 임뮤터블 변수 예시: 정수형 변수
a = 10
print(id(a)) # 정수 10의 메모리 주소 출력
a = 20
print(id(a)) # 정수 20의 메모리 주소 출력 (다른 주소)
이 예시에서 a 변수는 처음에 10을 가리키고, 그 다음에 20을 가리킵니다. id(a)를 출력해 보면, 두 값이 서로 다른 메모리 주소에 저장되어 있는 것을 확인할 수 있습니다.
2. 뮤터블 변수 (Mutable Variables)
뮤터블 변수는 값이 변경될 수 있는 변수입니다. 즉, 생성된 후에도 그 값을 수정할 수 있습니다. 대표적인 뮤터블 변수 타입에는 다음이 있습니다:
리스트 (list): 리스트는 요소들을 추가, 삭제 또는 변경할 수 있습니다.
딕셔너리 (dict): 딕셔너리는 키와 값을 추가, 삭제 또는 변경할 수 있습니다.
집합 (set): 집합도 요소를 추가하거나 삭제할 수 있습니다.
뮤터블 변수는 값이 변경될 수 있으므로, 값을 변경하더라도 메모리 주소가 변하지 않습니다. 예를 들어 봅시다:
# 뮤터블 변수 예시: 리스트
my_list = [1, 2, 3]
print(id(my_list)) # 리스트의 메모리 주소 출력
my_list.append(4)
print(id(my_list)) # 리스트에 요소를 추가한 후에도 같은 메모리 주소
이 예시에서 my_list는 처음에 [1, 2, 3]을 가리키고, 이후에 4를 추가하여 [1, 2, 3, 4]가 됩니다. id(my_list)를 출력해 보면, 리스트의 메모리 주소가 동일한 것을 확인할 수 있습니다.
3. 실습 예제
이제 몇 가지 예제를 통해 직접 확인해 보겠습니다:
# 임뮤터블 변수
x = "hello"
print("x의 id:", id(x)) # 첫 번째 id 출력
x += " world"
print("x의 새로운 id:", id(x)) # 두 번째 id 출력 (다른 주소)
# 뮤터블 변수
y = [1, 2, 3]
print("y의 id:", id(y)) # 첫 번째 id 출력
y.append(4)
print("y의 id:", id(y)) # 두 번째 id 출력 (같은 주소)
결과 설명 : 1. 임뮤터블 변수 x: 처음 "hello"일 때 id(x)는 특정 주소를 가리킵니다."hello world"로 바꾸면 새로운 문자열이 생성되므로 id(x)는 다른 주소를 가리킵니다.
2. 뮤터블 변수 y:처음 [1, 2, 3]일 때 id(y)는 특정 주소를 가리킵니다.4를 추가해도 여전히 같은 리스트이므로 id(y)는 같은 주소를 가리킵니다.
4. 중요한 차이점
임뮤터블 변수는 값이 변경되지 않으므로, 여러 곳에서 동시에 사용될 때 안전합니다. 예를 들어, 여러 함수에서 동일한 문자열 변수를 사용해도 그 값이 변경되지 않으므로 예기치 않은 오류가 발생할 가능성이 적습니다.
뮤터블 변수는 값이 변경될 수 있으므로, 주의해서 사용해야 합니다. 특히 함수에서 뮤터블 변수를 사용할 때는 그 변수가 의도하지 않게 변경되지 않도록 조심해야 합니다.
정수형(integer)이란 말 그대로 정수를 뜻하는 자료형을 말한다. 다음은 양의 정수와 음의 정수, 숫자 0을 변수 a에 대입하는 예이다.
>>> a = 123
>>> a = -178
>>> a = 0
실수형
파이썬에서 실수형(floating-point)은 소수점이 포함된 숫자를 말한다. 다음은 실수를 변수 a에 대입하는 예이다. 일반적으로 볼 수 있는 실수형의 소수점 표현 방식이다.
Copy>>> a = 1.2
>>> a = -3.45
02-2 문자열 자료형
큰따옴표로 양쪽 둘러싸기
"Hello World"
작은따옴표로 양쪽 둘러싸기
'Python is fun'
큰따옴표 3개를 연속으로 써서 양쪽 둘러싸기
"""Life is too short, You need python"""
작은따옴표 3개를 연속으로 써서 양쪽 둘러싸기
'''Life is too short, You need python'''
줄을 바꾸기 위한 이스케이프 코드\n삽입하기
>>> multiline = "Life is too short\nYou need python"
연속된 작은따옴표 3개 또는 큰따옴표 3개 사용하기
1번 방법의 단점을 극복하기 위해 파이썬에서는 다음과 같이 작은따옴표 3개(''') 또는 큰따옴표 3개(""")를 사용한다.
>>> multiline='''
... Life is too short
... You need python
... '''
작은따옴표 3개를 사용한 경우
>>> multiline="""
... Life is too short
... You need python
... """
문자열 인덱싱
>>> a = "Life is too short, You need Python"
위 코드에서 변수 a에 저장한 문자열의 각 문자마다 번호를 매겨 보면 다음과 같다.
"Life is too short, You need Python" 문자열에서 L은 첫 번째 자리를 뜻하는 숫자 0, i는 1 이런 식으로 계속 번호를 붙인 것이다. 즉, 중간에 있는 short의 s는 12가 된다.
문자열 인덱싱 활용하기
인덱싱의 예를 몇 가지 더 살펴보자.
>>> a = "Life is too short, You need Python"
>>> a[0]
'L'
>>> a[12]
's'
>>> a[-1]
'n'
>>> a = "Life is too short, You need Python"
>>> a[0:4]
'Life'
문자열 슬라이싱
a[0:4]는 a 문자열, 즉 "Life is too short, You need Python" 문자열에서 자리 번호 0부터 4까지의 문자를 뽑아 낸다는 뜻이다.
하지만 ‘a[0]은 L, a[1]은 i, a[2]는 f, a[3]은 e이므로 a[0:3]으로도 Life라는 단어를 뽑아 낼 수 있지 않을까?’라는 의문이 생길 것이다. 다음 예로 확인해 보자.
>>> a[0:3]
'Lif'
이렇게 되는 이유는 슬라이싱 기법으로 a[시작_번호:끝_번호]를 지정할 때 끝 번호에 해당하는 문자는 포함하지 않기 때문이다. 즉, a[0:3]을 수식으로 나타내면 다음과 같다.
0 <= a < 3
슬라이싱으로 문자열 나누기
다음은 자주 사용하는 슬라이싱 기법 중 하나이다.
>>> a = "20230331Rainy"
>>> date = a[:8]
>>> weather = a[8:]
>>> date
'20230331'
>>> weather
'Rainy'
f 문자열 포매팅
파이썬 3.6 버전부터는 f 문자열 포매팅 기능을 사용할 수 있다. 파이썬 3.6 미만 버전에서는 사용할 수 없는 기능이므로 주의해야 한다.
다음과 같이 문자열 앞에 f 접두사를 붙이면 f 문자열 포매팅 기능을 사용할 수 있다.
Copy>>> name = '홍길동'
>>> age = 30
>>> f'나의 이름은 {name}입니다. 나이는 {age}입니다.'
'나의 이름은 홍길동입니다. 나이는 30입니다.'
문자열 삽입 - join
>>> ",".join('abcd')
'a,b,c,d'
join 함수로 abcd 문자열의 각각의 문자 사이에 ‘,’를 삽입했다.
join 함수는 문자열뿐만 아니라 앞으로 배울 리스트나 튜플도 입력으로 사용할 수 있다(리스트와 튜플은 곧 배울 내용이므로 여기에서는 잠시 눈으로만 살펴보자). join 함수의 입력으로 리스트를 사용하는 예는 다음과 같다.
Copy>>> ",".join(['a', 'b', 'c', 'd'])
'a,b,c,d'
양쪽 공백 지우기 - strip
>>> a = " hi "
>>> a.strip()
'hi'
strip 함수는 문자열 양쪽에 있는 한 칸 이상의 연속된 공백을 모두 지운다.
문자열 바꾸기 - replace
>>> a = "Life is too short"
>>> a.replace("Life", "Your leg")
'Your leg is too short'
replace 함수는 replace(바뀔_문자열, 바꿀_문자열)처럼 사용해서 문자열 안의 특정한 값을 다른 값으로 치환해 준다.
문자열 나누기 - split
>>> a = "Life is too short"
>>> a.split()
['Life', 'is', 'too', 'short']
>>> b = "a:b:c:d"
>>> b.split(':')
['a', 'b', 'c', 'd']
split 함수는 a.split()처럼 괄호 안에 아무 값도 넣어 주지 않으면 공백([Space],[Tab],[Enter])을 기준으로 문자열을 나누어 준다. 만약 b.split(':')처럼 괄호 안에 특정 값이 있을 경우에는 괄호 안의 값을 구분자로 해서 문자열을 나누어 준다. 이렇게 나눈 값은 리스트에 하나씩 들어간다.['Life', 'is', 'too', 'short']나['a', 'b', 'c', 'd']가 리스트인데, 02-3에서 자세히 알아볼 것이므로 여기에서는 너무 신경 쓰지 않아도 된다.
리스트
여러 가지 리스트의 생김새는 다음과 같다.
>>> a = []
>>> b = [1, 2, 3]
>>> c = ['Life', 'is', 'too', 'short']
>>> d = [1, 2, 'Life', 'is']
>>> e = [1, 2, ['Life', 'is']]
리스트의 인덱싱
리스트 역시 문자열처럼 인덱싱을 적용할 수 있다. 먼저 a 변수에 [1, 2, 3] 값을 설정한다.
>>> a = [1, 2, 3]
>>> a
[1, 2, 3]
a[0]은 리스트 a의 첫 번째 요솟값을 말한다.
>>> a[0]
1
다음 예는 리스트의 첫 번째 요소인 a[0]과 세 번째 요소인 a[2]의 값을 더한 것이다.
>>> a[0] + a[2]
4
이것은 1 + 3으로 해석되어 값 4를 출력한다.
문자열을 공부할 때 이미 살펴보았지만, 파이썬은 숫자를 0부터 세기 때문에 a[1]이 리스트 a의 첫 번째 요소가 아니라 a[0]이 리스트 a의 첫 번째 요소라는 것을 명심하자. a[-1]은 문자열에서와 마찬가지로 리스트 a의 마지막 요솟값을 말한다.
Copy>>> a[-1]
3
리스트의 슬라이싱
문자열과 마찬가지로 리스트에서도 슬라이싱 기법을 적용할 수 있다. 슬라이싱은 ‘잘라 낸다’라는 뜻이라고 했다. 리스트의 슬라이싱에 대해서 살펴보자.
>>> a = [1, 2, 3, 4, 5]
>>> a[0:2]
[1, 2]
앞의 예를 문자열에서 슬라이싱했던 예와 비교해 보자.
>>> a = "12345"
>>> a[0:2]
'12'
2가지가 완전히 동일하게 사용되었다는 것을 눈치챘을 것이다. 문자열에서 했던 것과 사용법이 완전히 동일하다.
몇 가지 예를 더 살펴보자.
>>> a = [1, 2, 3, 4, 5]
>>> b = a[:2]
>>> c = a[2:]
>>> b
[1, 2]
>>> c
[3, 4, 5]
b 변수는 리스트 a의 첫 번째 요소부터 두 번째 요소인 a[1]까지 나타내는 리스트이다. 물론 a[2] 값인 3은 포함되지 않는다. c라는 변수는 리스트 a의 세 번째 요소부터 끝까지 나타내는 리스트이다.
리스트 길이 구하기
리스트 길이를 구하기 위해서는 다음처럼 len 함수를 사용해야 한다.
>>> a = [1, 2, 3]
>>> len(a)
3
len은 문자열, 리스트 외에 앞으로 배울 튜플과 딕셔너리에도 사용할 수 있는 함수이다. 실습에서 자주 사용하므로 잘 기억해 두자.
메모 넣기(comment) - 주의 점 - 메모가 이미 추가된 곳에 메모를 넣으면 오류 발생(삭제 후 추가) - 메모에는 텍스트만 입력 가능
Sub delComment()
With ActiveSheet.Range("A1")
.Interior.ColorIndex = 0
.ClearComments
End With
End Sub
Sub addComment()
With ActiveSheet.Range("A1")
'메모 삭제
.ClearComments
.Interior.ColorIndex = 12
'메모 넣기(문자열만 입력가능, 기존 메모가 있는데 넣으면 오류발생)
.addComment ("hello world")
End With
End Sub
숫자를 문자로 변환(Format) - 주의 점 - 충분히 큰 숫자를 감안하여 long 형으로 인자를 받음
Function numberToText(num As Long) As String
numberToText = Format(num, "#,##0") ' 숫자를 포맷팅된 문자열로 변환 (예: 1,234,567)
End Function
딕셔너리(Dictionary) - 착안 점 - 엑셀은 행, 열의 2차원 배열임. - key 에는 데이터의 중복이 없는 키 값을 넣고 - value 에는 행번호를 넣고 - 나머지 컬럼 번호는 Enum 으로 처리하여 - A-B 시트를 키값으로 매칭하여 데이터를 가져오는 코드를 작성가능 ex) 하나의 통일된 서식을 여러 부서에 뿌려서 취합할 경우 유용한 코딩 기법
Sub GetValuesFromSheet2()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim dict1 As Object
Dim dict2 As Object
Dim key1 As String
Dim key2 As String
Dim i As Long
Dim j As Long
' 시트 설정
Set ws1 = ThisWorkbook.Sheets("1번 시트")
Set ws2 = ThisWorkbook.Sheets("2번 시트")
' 딕셔너리 생성
Set dict1 = CreateObject("Scripting.Dictionary")
Set dict2 = CreateObject("Scripting.Dictionary")
' 1번 시트 값 저장
For i = 2 To ws1.UsedRange.Rows.Count
key1 = ws1.Cells(i, 1).Value & "," & ws1.Cells(i, 2).Value
dict1.Add key1, i
Next
' 2번 시트 값 저장
For j = 2 To ws2.UsedRange.Rows.Count
key2 = ws2.Cells(j, 1).Value & "," & ws2.Cells(j, 2).Value
dict2.Add key2, j
Next
' 2번 시트 값 가져오기
For i = 2 To ws1.UsedRange.Rows.Count
key1 = ws1.Cells(i, 1).Value & "," & ws1.Cells(i, 2).Value
If dict2.Exists(key1) Then
ws1.Cells(i, 4).Value = ws2.Cells(dict2(key1), 4).Value
End If
Next
' 메모리 해제
Set dict1 = Nothing
Set dict2 = Nothing
End Sub
Body 영역선택(currentRegion & offset & resize) - 내용 : header를 제외한 내용만 선택하는 코드
' ======================================================================================
' 설명: 데이터 시작 행부터 끝까지의 전체 데이터 범위를 설정하는 서브루틴
' ======================================================================================
Sub seletAllData()
Dim DATA_START_ROW As Integer '데이터 시작 행 번호를 저장할 변수
Dim allRange As Range '전체 데이터 범위를 저장할 변수
DATA_START_ROW = 2 '데이터 시작 행 번호를 2로 설정
' 전체 데이터 범위 설정
With Range("A1").CurrentRegion
Set allRange = .Offset(DATA_START_ROW - 1).Resize(.Rows.Count - DATA_START_ROW + 1)
' A1 셀의 현재 데이터 영역에서 DATA_START_ROW 행부터 데이터가 끝나는 행까지의 범위를 allRange에 저장
End With
allRange.Select '전체 데이터 범위 선택 (주석 처리됨)
End Sub
Column 영역선택(columns) - 내용 : header를 제외한 내용 중 특정 컬럼 영역만 선택
'======================================================================================
' 설명: 데이터 시작 행부터 끝까지의 특정 컬럼 데이터 범위를 선택하는 서브루틴
' ======================================================================================
Sub selectColData()
Dim DATA_START_ROW As Integer '데이터 시작 행 번호를 저장할 변수
Dim allRange As Range '전체 데이터 범위를 저장할 변수
Dim colNum As Integer '선택할 컬럼 번호를 저장할 변수
DATA_START_ROW = 2 '데이터 시작 행 번호를 2로 설정
colNum = 1 '선택할 컬럼 번호를 1로 설정 (A 열)
' 전체 데이터 범위 설정
With Range("A1").CurrentRegion
Set allRange = .Offset(DATA_START_ROW - 1).Resize(.Rows.Count - DATA_START_ROW + 1)
' A1 셀의 현재 데이터 영역에서 DATA_START_ROW 행부터 데이터가 끝나는 행까지의 범위를 allRange에 저장
End With
allRange.Columns(colNum).Select '전체 데이터 범위에서 colNum 번째 컬럼을 선택
End Sub
파일순회
Sub PrintFilesWithSpecificExtension()
Dim fileName As String
Dim extension As String
' 출력할 확장자 설정
extension = "*.hw*" ' 예: .txt 파일
' 현재 폴더에서 첫 번째 파일 이름 가져오기
fileName = Dir(extension)
' 파일 이름이 있는 동안 반복
Do While fileName <> ""
Debug.Print fileName
' 다음 파일 이름 가져오기
fileName = Dir
Loop
End Sub
파일순회 및 파일 내용 출력
Sub PrintFilesWithSpecificExtension()
Dim pathName As String
Dim fileName As String
Dim extension As String
pathName = ThisWorkbook.Path & "\취합폴더\"
' 출력할 확장자 설정
extension = pathName & "*.xl*" '
' 현재 폴더에서 첫 번째 파일 이름 가져오기
fileName = Dir(extension)
' 파일 이름이 있는 동안 반복
Do While fileName <> ""
Debug.Print fileName
Call fileOpenAndClose(pathName & fileName)
' 다음 파일 이름 가져오기
fileName = Dir
Loop
End Sub
Function fileOpenAndClose(fileName As String)
'Dim fileName As String
Dim targetWb As Workbook
'fileName = "3.신속집행계획(총무과).xlsx"
'파일 열기
Set targetWb = Workbooks.Open(fileName)
Debug.Print (targetWb.Worksheets(1).Range("A1").Value)
'파일 저장 없이 닫기
targetWb.Close savechanges:=False
End Function
Sub fileOpenAndClose_test()
Dim pathName As String
Dim fileName As String
fileName = "3.신속집행계획(총무과).xlsx"
pathName = ThisWorkbook.Path & "\취합폴더\"
Call fileOpenAndClose(pathName & fileName)
End Sub
파일순회 및 이름변경
Function 파일이름변경(oldFileName, newFileName)
' 파일명 변경
Name oldFileName As newFileName
End Function
Sub 제출부서카운트()
Dim 폴더경로 As String, 파일명 As String
Dim 부서명 As String
Dim 제출여부확인시트 As Worksheet
Dim 부서명리스트 As Range
'부서명 = "도시재생과"
Application.ScreenUpdating = False
폴더경로 = ThisWorkbook.Path & "\취합폴더\" '폴더경로 설정
파일명 = Dir(폴더경로 & "*.xls*") '폴더 내의 모든 파일 목록 가져오기
'제출여부확인 시트를 추가하고, 부서명 리스트를 작성
Set 제출여부확인시트 = ActiveSheet
With 제출여부확인시트
'부서명리스트 세팅
Set 부서명리스트 = Range(.Range("B2"), .Range("B2").End(xlDown))
End With
'Debug.Print (rng.Value)
Do While 파일명 <> ""
For Each rng In 부서명리스트
'Debug.Print (파일명 & "- " & rng.Value)
'파일명에 부서명이 있으면
If InStr(1, 파일명, rng.value) > 0 Then
'Debug.Print (파일명)
rng.Offset(, 1).value = 1 + rng.Offset(, 1).value
If InStr(1, 파일명, rng.Offset(, -1).value & ".") = 0 Then
Call 파일이름변경(폴더경로 & 파일명, _
폴더경로 & rng.Offset(, -1).value & "." & 파일명)
End If
End If
Next
파일명 = Dir '다음 파일 이름 가져오기
Loop
Application.ScreenUpdating = True
End
파일 열고 닫기
Sub fileOpenAndClose()
Dim fileName As String
Dim targetWb As Workbook
fileName = "3.신속집행계획(총무과).xlsx"
'파일 열기
Set targetWb = Workbooks.Open(ThisWorkbook.Path & "\취합폴더\" & fileName)
'파일 저장 없이 닫기
targetWb.Close savechanges:=False
End Sub
중복값 제거 - 특정 데이터의 컬럼영역에 대해 중복값 제거
' ======================================================================================
' 설명: 활성 시트의 B 열에서 중복된 데이터를 제거하는 서브루틴
' ======================================================================================
Sub removeDuplicateData()
With ActiveSheet
' B2 셀부터 B 열의 마지막 행까지 범위 선택
' 선택된 범위에서 B 열(1번째 열)을 기준으로 중복 데이터 제거
' Header 옵션을 xlNo로 설정하여 첫 번째 행을 헤더로 취급하지 않음
Range(.Range("B2"), .Range("B2").End(xlDown)).RemoveDuplicates Columns:=1, Header:=xlNo
End With
End Sub
Enum - 주로 컬럼명에 매칭하여 사용
Public Enum TargetColumns
DATA_START_ROW = 4
회계 = 1
부서 = 2
사업 = 3
통계목 = 4
당해예산액 = 6
이월예산액 = 8
기집행액 = 12
End Enum