변수
1. 변수란?
1.1 변수는 가리키는 것
변수는 변하는 값
이라는 뜻을 가지고 있습니다.
여기서 변수는 name
과 age
입니다. name
은 Licat
이라는 값을, 변수 age
는 30
이라는 값을 가리킵니다. 변수가 수학에서처럼 저장하는 개념이 아니기에 포스트잇에 비유할 수 있습니다. Licat
값에 name
이라는 포스트잇을 붙이고, 30
값에 age
라는 포스트잇을 붙인다고 생각하면 됩니다.
앞으로는 이 교안에서 변수와 값의 관계는 아래와 같은 화살표로 표시합니다.
1.2 변수 생성해보기
파이썬에서 변수를 만드는 것은 매우 간단합니다. 변수 이름을 정하고, 등호(=
) 기호를 사용하여 변수에 값을 할당하면 됩니다. 변수의 값을 변경해보고 변경된 값을 확인해보세요.
이 예제에서 'age'라는 변수에 30이라는 값을, 'name'이라는 변수에 'Jun'이라는 값을 할당했습니다. 이는 아래와 같은 화살표가 그려지는 것입니다.
1.3 변수가 가리키는 값
x = 10
y = x
z = y
x = 10
y = x
z = y
만약 위와 같이 변수를 생성하면 변수들이 어떤 관계가 될지 생각해보세요.
혹시 위와 같이 변수가 생성되었다고 생각한다면 오해입니다. 만약 위 화살표였다면 x가 가리키고 있는 값이 변했을 때 y와 z도 값이 변해야겠죠.
결과는 예상과 다릅니다. x를 20으로 변경했지만 y와 z는 10으로 출력됩니다. 그 이유는 앞서 살펴본 코드에서 변수 x, y, z와 값 20의 관계와 x를 10에서 20으로 바꾸는 과정이 다음과 같기 때문입니다.
x = 10
y = x
z = y
x = 10
y = x
z = y
그리고 두 번째 예제는 아래와 같이 그려집니다.
그림을 보면 x = 20
을 실행할 때 x
가 10
을 가리키다가 20
을 가리키고, 기존의 y
, z
는 여전히 10
을 가리키고 있습니다.
변수의 개념은 언어마다 다릅니다.
C와 같은 다른 언어에서 배우는 변수 개념으로 파이썬을 이해하시면 혼란이 올 수 있습니다. C는 변수가 값을 '가리키는 것'이 아니라 값이 '담겨'있습니다. 이 수업에서 필요 이상의 개념, 예를 들어 C언어나 JAVA언어를 함께 설명하진 않습니다. 여기서 가져가야할 포인트는 '변수의 개념이 언어마다 다르다'입니다.
2. 변수 이름 짓는 규칙 알아보기
2.1 변수 이름
변수의 이름을 정할 때는 몇 가지 규칙을 따라야 합니다. 이러한 변수 규칙은 처음부터 모두 외우기 어려우니, 수업을 진행하면서 자연스럽게 익히시면 됩니다. 모르는 내용이 있더라도 한 번 읽어보시고 넘어가셔도 됩니다. 이후에 다시 찾아보면서 익히시면 됩니다.
-
변수 이름은 알파벳(대문자와 소문자), 숫자, 언더스코어(_)로 구성됩니다.
다음과 같이 π와 같은 일부 특수 문자를 사용해도 실행에는 문제가 없으나 개발자 문화에서는 관습적으로 허락하지 않습니다.
π = 100 π + π
π = 100 π + π
-
변수 이름은 숫자로 시작할 수 없습니다. 예를 들어
1ten
,100_test
,0
은 변수 이름으로 사용할 수 없습니다. -
파이썬의 키워드(예: if, else, while 등)는 변수 이름으로 사용할 수 없습니다. 아래 코드로 파이썬에서 사용하고 있는 키워드를 확인할 수 있습니다.
import keyword print(keyword.kwlist) -
변수 이름은 대소문자를 구분합니다. (예: 'name', 'Name', 'NAME'은 서로 다른 변수입니다.)
name = 'Jun1' Name = 'Jun2' NAME = 'Jun3' print(name, Name, NAME) -
관습
- 일반 변수는 주로 첫 문자를 소문자로 사용합니다.
- 사용하지 않는 변수는 언더스코어(
_
)로 명명합니다. 예를 들어 반복문에서 i, j, k와 같은 변수가 사용되지 않는다면 이러한 변수명을 언더스코어로 대체합니다. 이를 통해 다른 개발자가 해당 변수가 사용되지 않는다는 것을 알 수 있습니다. - 클래스는 첫문자를 대문자로 하고 띄어쓰기가 일어날 때마다 대문자로 표시하는 파스칼표기법을 주로 사용합니다. 예를 들어 아래와 같이 표기될 수 있습니다.
class UserProfile: pass
class UserProfile: pass
- 변수 이름은 띄어쓰기를 언더바로 나타내는 스네이크 표기법을 주로 사용합니다. 예를 들어 아래와 같이 표기될 수 있습니다.
daily_user_count = 100
daily_user_count = 100
스네이크 표기법은 언더스코어로 띄어쓰기를 표기하는 방법입니다. 언더스코어로 연결된 단어의 모습이 뱀 같다 하여 스네이크 표기법이라고 합니다. 예를 들어 아래와 같이 표기될 수 있습니다.
daily_user_count = 100
daily_user_count = 100
스네이크 표기법 말고도 다른 방법도 있습니다. 카멜 표기법은 언더스코어 대신 중간 문자를 대문자로 하는 표기법입니다. 중간에 대문자가 툭 튀어 나온 모양이 '낙타 등 같다'하여 카멜 표기법이라고 합니다.
dailyUserCount = 100
dailyUserCount = 100
파스칼 표기법도 있습니다. 파스칼 표기법은 카멜 표기법과 비슷하지만 맨 앞 문자를 대문자로 표기하는 것입니다. 파스칼 표기법은 변수가 아니라 클래스를 명명할 때 많이 사용합니다.
class User: pass
class User: pass
2.2 올바른 변수 이름의 예
name
age
user_name
User
_temp
PI
2.3 잘못된 변수 이름의 예
1user
(숫자로 시작합니다)user-name
(하이픈(-)은 허용되지 않습니다)if
(Python의 키워드입니다)!for
(특수문자는 사용할 수 없습니다)
3. 변수의 타입
변수의 타입은 해당 변수를 어떻게 관리하고 처리할 것인지를 결정합니다. 변수의 타입에 따라 컴퓨터는 메모리를 할당하고 값을 처리하거나 연산하는 등 해석하는 방식이 달라집니다.
위 코드에서 age에는 30이라는 숫자를, name에는 "licat"이라는 문자열을 할당합니다. 이때 age와 name은 서로 다른 타입을 가지게 됩니다. age는 정수(int) 타입이고, name은 문자열은 문자열(str) 타입입니다. 그림으로 표현해보면 다음과 같습니다.
그림에서 보듯이 값(value)은 이미 타입을 가지고 있는 객체
입니다. 정확히는 값과 타입을 가지고 있는 인스턴스
입니다. 객체와 인스턴스에 대한 상세 내용은 클래스파트에서 다룹니다. 만약 이것에 대한 개념이 없다면 실체
정도로 이해를 부탁드립니다. 변수는 해당 객체를 참조할 뿐입니다. 참조한다는 것은 화살표로 가리키고 있다는 것입니다. 따라서 변수의 타입을 출력하는 것은 실제로 그 변수가 참조하는 객체의 타입을 출력하는 것입니다. 이러한 객체의 타입 설정은 파이썬이 자동으로 처리합니다.
변수의 타입은 해당 변수를 어떻게 관리하고 처리하며 활용할지를 알려줍니다. 예를 들어, 문자열의 덧셈은 두 문자열을 이어 붙이는 연산이지만, 숫자의 덧셈은 두 수를 더하는 연산입니다. 컴퓨터 내부적으로는 모든 데이터가 0과 1로 이루어진 이진수로 표현되기에 문자열도 정수처럼 더할 수 있지만, 변수의 타입을 통해 더하지 않고 이어붙이는 것입니다.
위 예제에서, 처음에 x
에 10
을 할당하면, x
의 타입은 정수(int)
가 됩니다. 그 값이 정수이기 때문입니다. 다시 x
에 licat
을 할당하면, x
의 타입은 문자열(str)
이 됩니다. 그 값이 문자열이기 때문입니다.
이것이 얼마나 편한지 파이썬으로 프로그래밍을 처음 접하시는 분들은 체감하지 못합니다. 다른 일부 언어는 일일이 이 타입을 지정해주어야 합니다. 아래처럼요.
// c언어 예제
int x = 10;
char y = 'licat';
// c언어 예제
int x = 10;
char y = 'licat';
파이썬에서 타입이 자동으로 지정되기에 이러한 과정이 필요하지 않습니다. 이러한 특징을 동적 타이핑(dynamic typing)
이라고 합니다. 동적 타이핑은 변수의 타입을 자동으로 지정하고, 해당 타입에 맞게 변수를 처리하므로 개발자가 타입을 일일이 지정해주지 않아도 되어 편리합니다.
파이썬에서도 타입을 지정하는 것이 가능합니다. 특히 다른 언어를 사용하다 파이썬을 처음 접하면 동적 타이핑
이 견고하지 못한 코드를 작성한다
라고 생각하여 항상 타입을 명시하기도 하는데 이는 파이썬의 설계 철학과 맞는 방식은 아닙니다. 프로젝트에 따라, 구성원에 따라, 필요에 따라 타입명시를 적절하게 사용하세요. 보통의 경우에는 타입명시를 하지 않습니다.
파이썬에서 객체의 타입을 확인하는 데 type()
함수를 사용하고, 해당 타입이 가진 속성과 메서드를 확인하는 데 dir()
함수를 사용합니다. 실무에서도 이 두 함수를 함께 사용해 타입의 속성과 기능을 파악하는데 자주 사용하니 꼭 기억해주세요. 초급자뿐만 아니라 중급자에게도 새로운 객체를 다룰 때 해당 객체의 타입과 속성을 파악하는 데 도움이 됩니다.
# 출력
<class 'int'> # int라는 이름을 가지고 있군요!
['__abs__', # 매직 메서드: 절대값이 되는군요!
'__add__', # 매직 메서드: 더하기가 되는군요!
'__and__', # 매직 메서드: 논리 연산이 되는군요!
# ...생략...
'__mul__', # 매직 메서드: 곱하기가 되는군요!
# ...생략...
'real', # 메서드: 실수부를 출력하는 메서드
'to_bytes' # 메서드: 바이트로 변환하는 메서드
]
# 출력
<class 'int'> # int라는 이름을 가지고 있군요!
['__abs__', # 매직 메서드: 절대값이 되는군요!
'__add__', # 매직 메서드: 더하기가 되는군요!
'__and__', # 매직 메서드: 논리 연산이 되는군요!
# ...생략...
'__mul__', # 매직 메서드: 곱하기가 되는군요!
# ...생략...
'real', # 메서드: 실수부를 출력하는 메서드
'to_bytes' # 메서드: 바이트로 변환하는 메서드
]
dir()
함수의 출력 결과는 크게 매직 메서드(magic method)와 일반 속성 및 메서드로 나눌 수 있습니다. 이 개념은 클래스에서 다루게 됩니다. 여기서는 가볍게 살펴도보록 하겠습니다.
언더바가 2개씩 감싸고 있는 매직 메서드
라고 불리는 것들로 해당 타입의 객체가 수행할 수 있는 연산이나 기능을 파악할 수 있습니다. 예를 들어, int 타입은 __add__
, __sub__
, __mul__
, __truediv__
등의 매직 메서드를 가지고 있어 산술 연산이 가능합니다. 반면에 str 타입은 __add__
매직 메서드를 가지고 있어 문자열 연결 연산은 가능하지만, __sub__
매직 메서드가 없기 때문에 뺄셈 연산은 지원하지 않습니다.
언더바가 양쪽에 없는 일반 속성
과 메서드
는 해당 타입의 객체가 가지고 있는 속성 값과 기능(메서드)을 나타냅니다. 예를 들어, int 타입은 real
, imag
, bit_length
등의 속성과 메서드를 가지고 있어 정수의 실수부, 허수부, 비트 길이 등을 확인할 수 있습니다. str 타입은 lower
, upper
등의 메서드를 가지고 있어 문자열을 대문자로 변환하거나 소문자로 변환하는 등의 기능을 수행할 수 있습니다.
4. 변수 값 변경
파이썬에서 변수는 값을 저장하는 것이 아니라 값을 참조합니다. 따라서 변수에 새로운 값을 할당하면 해당 변수는 이전 값 대신 새로운 값을 참조하게 됩니다. 여기서 참조라는 말은 변수가 객체를 가리킨다는 의미입니다. 따라서 가리키는 화살표가 할당을 할 때마다 바뀌게 됩니다.
x = 10
print(x) # 출력: 10
x = 20
print(x) # 출력: 20
x = "Hello"
print(x) # 출력: Hello
x = 10
print(x) # 출력: 10
x = 20
print(x) # 출력: 20
x = "Hello"
print(x) # 출력: Hello
위 예제에서 x
는 처음에 정수 객체 10
을 참조합니다. 그 후에 x
에 정수 객체 20
을 할당하면 x
는 더 이상 10
을 참조하지 않고 20
을 참조하게 됩니다. 마지막으로 x
에 문자열 객체 "Hello"
를 할당하면 x
는 20
을 참조하지 않고 "Hello"
를 참조하게 됩니다. 만약 참조라는 말이 어렵다면 화살표를 생각해주세요. x
는 10
을 가리켰다가 20
을 가리키고, Hello
를 가리키게 됩니다.
이처럼 파이썬에서는 변수에 새로운 값을 할당할 때마다 해당 변수가 참조하는 객체가 변경됩니다. 이를 통해 변수의 값을 동적으로 변경할 수 있으며, 변수의 타입도 동적으로 변경될 수 있습니다.
5. 변수 삭제
파이썬에서는 del
키워드를 사용하여 변수를 삭제할 수 있습니다. 변수를 삭제한다는 것은 해당 변수의 참조를 해제하고 메모리에서 제거한다는 것을 의미합니다.
x = 10
print(x) # 출력: 10
del x
print(x) # NameError: name 'x' is not defined
x = 10
print(x) # 출력: 10
del x
print(x) # NameError: name 'x' is not defined
위 예제에서 x
에 정수 객체 10
을 할당한 후 del
키워드를 사용하여 x
를 삭제합니다. 삭제 후에는 더 이상 x
를 사용할 수 없으며, x
를 참조하려고 하면 NameError
가 발생합니다.
변수 삭제는 메모리 관리 측면에서 중요합니다. 파이썬은 자동 메모리 관리(가비지 컬렉션, 참조 횟수가 0인 사용하지 않는 변수를 메모리 해제하는 기능)를 수행하지만, 불필요한 변수를 삭제하면 메모리 사용을 최적화할 수 있습니다. 특히 대용량 데이터를 다룰 때는 메모리 사용을 최적화하는 것이 중요합니다.
다음은 변수 삭제의 또 다른 예시입니다.
x = 10
y = x
del x
print(y) # 출력: 10
print(x) # NameError: name 'x' is not defined
x = 10
y = x
del x
print(y) # 출력: 10
print(x) # NameError: name 'x' is not defined
위 예제에서 x
에 10
을 할당하고 y
에 x
를 할당합니다. 이때 y
는 x
와 같은 객체 10
을 참조합니다. 그 후에 x
를 삭제하더라도 y
는 여전히 10
을 참조하고 있기 때문에 y
를 출력하면 10
이 출력됩니다. 하지만 x
는 삭제되었으므로 더 이상 사용할 수 없습니다.
변수 삭제는 신중하게 사용해야 합니다. 삭제된 변수를 참조하려고 하면 NameError
가 발생하므로 코드의 오류를 유발할 수 있습니다. 따라서 변수 삭제는 꼭 필요한 경우에만 사용하는 것이 좋습니다.
아래 코드는 [1, 2, 3]
가 더 이상 x
변수에 의해 참조되지 않기 때문에, 쉽게 얘기하여 화살표가 사라졌기 때문에 가비지 컬렉터에 의해 자동으로 메모리에서 해제됩니다.
x = [10, 20, 30]
x = 'hello world'
x = [10, 20, 30]
x = 'hello world'
6. 변수의 다양한 타입
파이썬에서는 다양한 타입의 변수를 사용할 수 있습니다. 각 타입은 데이터를 저장하고 처리하는 방식에 따라 구분됩니다. 여기서는 변수의 타입을 개괄적으로 살펴보고, 이후 챕터에서 각 타입에 대해 자세히 다루도록 하겠습니다.
파이썬의 내장 타입은 크게 다음과 같이 분류할 수 있습니다.
-
숫자 타입(Numeric Types): 숫자를 다룹니다.
- 정수형(int): 양의 정수, 0, 음의 정수를 표현합니다. 예: 1, 5, 100, 0, -30, -45
- 실수형(float): 소수점을 포함한 실수를 표현합니다. 예: 1.5, 5.6, 100.23, 0.0, -30.53245
- 복소수형(complex): 실수부와 허수부로 구성된 복소수를 표현합니다. 예: 1+2j, 3-4j
-
논리 타입(Boolean Type): True, False을 표현합니다.
-
시퀀스 타입(Sequence Types): 순서가 있으면서 순서에 해당하는 값을 읽어올 수 있는 인덱싱, 일부 순서에 그룹을 잘라낼 수 있는 슬라이싱이 가능한 자료형입니다.
- 문자열(str): 문자의 나열로 이루어진 문자열을 표현합니다. 예: "Hello", 'Python'
- 리스트(list): 순서가 있는 변경 가능(mutable)한 객체의 집합입니다. 예: [1, 2, 3], ['a', 'b', 'c']
- 튜플(tuple): 순서가 있는 변경 불가능(immutable)한 객체의 집합입니다. 예: (1, 2, 3), ('a', 'b', 'c')
-
컬렉션 타입(Collection Types) 혹은 컨테이너 타입(Container Types): 다른 자료형을 담을 수 있는 자료형입니다.
- 리스트(list): 순서가 있는 변경 가능(mutable)한 객체의 집합입니다. 예: [1, 2, 3], ['a', 'b', 'c']
- 튜플(tuple): 순서가 있는 변경 불가능(immutable)한 객체의 집합입니다. 예: (1, 2, 3), ('a', 'b', 'c')
- 집합(set): 순서가 없고 중복을 허용하지 않는 변경 가능(mutable)한 객체의 집합입니다. 예: {1, 2, 3}, {'a', 'b', 'c'}
- 딕셔너리(dict): 키(key)와 값(value)의 쌍으로 이루어진 변경 가능(mutable)한 객체의 집합입니다. 예: {'a': 1, 'b': 2, 'c': 3}
-
None 타입: None, 값이 없음을 나타내는 특별한 타입입니다.
이 외에도 파이썬에서는 함수(function), 클래스(class), 모듈(module) 등의 타입도 존재합니다. 각 타입의 변수를 선언하고 사용하는 예시를 살펴보겠습니다.
a = 10 # int, 정수형
b = -1 # int, 정수형
c = 0b110 # int, 2진수 정수형
d = 0o56 # int, 8진수 정수형
e = 0xAC # int, 16진수 정수형
f = 10.1 # float, 실수형
g = 10 + 2j # complex, 복소수형
h = 'Hello' # str, 문자열
i = "10" # str, 문자열
j = True # bool, 불리언
k = None # NoneType
l = [1, 2, 3, 4] # list, 리스트
m = ['one', 'two'] # list, 리스트
n = (1, 2, 3, 4) # tuple, 튜플
o = ('one', 'two') # tuple, 튜플
p = {'one': 1, 'two': 2} # dict, 딕셔너리
q = {1, 2, 3, 4} # set, 집합
def r(): # function, 함수
pass
s = print # built-in function, 내장 함수
t = lambda x: x ** 2 # function, 람다 함수
u = int # type, 타입
class Character: # class, 클래스
pass
hero = Character() # instance, 인스턴스
villain = Character() # instance, 인스턴스
a = 10 # int, 정수형
b = -1 # int, 정수형
c = 0b110 # int, 2진수 정수형
d = 0o56 # int, 8진수 정수형
e = 0xAC # int, 16진수 정수형
f = 10.1 # float, 실수형
g = 10 + 2j # complex, 복소수형
h = 'Hello' # str, 문자열
i = "10" # str, 문자열
j = True # bool, 불리언
k = None # NoneType
l = [1, 2, 3, 4] # list, 리스트
m = ['one', 'two'] # list, 리스트
n = (1, 2, 3, 4) # tuple, 튜플
o = ('one', 'two') # tuple, 튜플
p = {'one': 1, 'two': 2} # dict, 딕셔너리
q = {1, 2, 3, 4} # set, 집합
def r(): # function, 함수
pass
s = print # built-in function, 내장 함수
t = lambda x: x ** 2 # function, 람다 함수
u = int # type, 타입
class Character: # class, 클래스
pass
hero = Character() # instance, 인스턴스
villain = Character() # instance, 인스턴스
변수를 분석할 때에는 아래 3개를 세트로 묶어 출력해보도록 하세요. 기본 자료형을 만날 때 뿐만 아니라, 모듈에서 제공하고 있는 자료형이나 여러분이 작성한 자료형에서도 마찬가지입니다. 이를 통해 출력되는 값, 검색할 키워드, 가진 속성 등을 확인할 수 있습니다. 이에 대한 내용은 각각의 자료형에서 상세히 다룹니다.
print(a)
print(type(a))
print(dir(a))
print(a)
print(type(a))
print(dir(a))
파이썬 GitHub에서 파이썬이 어떻게 구현되어 있는지 확인할 수 있습니다. 예를 들어 list의 구현체가 궁금하다면 아래 링크를 참고할 수 있습니다. 다만 C언어로 작성되어 있어서 이해하기 어려울 수 있습니다. 파이썬은 C언어로 작성되어 있기 때문입니다.
파이썬 List 구현체7. 매직 메서드 수정해보기
앞서 언급한 매직 메서드를 조금 수정하면 아래와 같이 더하면 곱하기가 되게 하고, 곱하면 더하기가 되게 할 수도 있습니다. 여러분이 하시는 단순한 연산도 어딘가에 코드로 정의되어(작성되어) 있습니다. 아래 코드는 가능하면 실행시키지 마세요. 이 코드를 실행시키면 위니북스에서는 새로고침을, 코랩에서는 런타임을 재시작해야 합니다.
만약 위 코드를 코랩에서 실행시켰다면 런타임을 재실행해야하고 위니북스에서는 새로고침을 해야합니다. 때에 따라서는 캐시를 지우는 강력 새로고침이 필요할 수도 있습니다. 이는 마치 아래와 같은 코드를 실행한 것과 같습니다. 되돌릴 수 없는 코드를 작성한 것이죠. 아래 코드를 실행시키면 런타임을 재시작 하지 않으면 print를 사용할 수 없습니다. 마찬가지로 위 코드는 런타임을 재실행하지 않으면 int를 사용해서 더하기를 할 때마다 곱하기가 되버립니다.
print = 100 # 이 코드를 실행시켜버리면 이제 print를 사용할 수 없습니다.
print = 100 # 이 코드를 실행시켜버리면 이제 print를 사용할 수 없습니다.