- 참조에 의한 변수와 객체 연결 2023.01.11
- Python에서 집합을 사용하는 이유 2023.01.10
- 반내림 vs 내림(Python3) 2023.01.05
- __name__ 2022.11.16
Python의 변수와 참조
변수는 일반적으로 데이터를 저장할 수 있는 메모리 공간을 의미한다.
다만, 파이썬에서의 변수는 C, 자바 같은 컴파일 언어에서의 변수와는 차이가 있다.
자바를 예로 들면 자바는 변수를 선언하면서 선언된 자료형 만큼의 메모리를 확보한다. 더 정확하게 말하면 원시 타입(Primitive Type)에 해당하는 변수(int, double, boolean 등)를 선언하면 선언된 타입 만큼의 크기의 영역을 Stack 메모리에 선언한다. 그리고 객체와 메서드 같은 참조형 타입(Reference type)은 Heap 메모리에 실질적인 데이터가 저장되고 그 데이터의 주소값이 stack 메모리에 저장되는 형태이다.
하지만 파이썬의 변수는 다르다.
파이썬에서 변수는 타입에 의해 선언되는게 아닌 객체와 연관되어 있다.
왜냐하면 변수에 선언되는 데이터는 모두 객체이기 때문이다.
아래에서 조금 더 구체적으로 살펴보겠다.
만약
a = 10 이라는 python 구문이 있다면,
파이썬은 우선 10을 나타내는 객체를 생성한다.
이후 변수 a를 생성하고 변수 a와 객체 10을 연결한다.
즉, a와 객체 10은 다른 위치에 저장되고 이 둘은 참조에 의해 연결된다.
다른 예시를 살펴보면
a = 10
a = "ten"
이 경우 a의 타입이 정수타입에서 문자열타입으로 변경된 것이 아니라
변수 a가 객체 10을 참조했다가, 객체 "ten"을 참조하는 것이다.
왜냐하면 파이썬에서의 변수는 타입을 가지지 않는다. 그래서 a의 타입은 변경할 수 없다.
그래서 변수는 사실상 특정 객체를 참조하고만 있는 것이다.
그렇다고 파이썬에 타입이 아예 없는 것은 아니다.
객체들이 타입 정보를 갖고 있다. 각각 객체의 헤더에 타입 정보가 저장된다고 한다. 이처럼 객체 자신이 자신의 타입을 알고 있으므로 변수에 타입을 저장할 필요가 없다.
그러면 이런 생각이 들 수 있다.
a = 10
b = 10
이 경우 10과 10은 같은 객체 인건가? 그렇다면 a에 +5를 하면 b의 값도 변하는 것인가?
하나씩 답을 해보면 아래와 같다.
10과 10은 같은 객체이다.
이는 파이썬 구문으로 확인 가능하다.
파이썬에서 == 는 값이 같은지 확인하고 'is'는 같은 객체를 참조하고 있는지를 확인해 준다.
a = 10
b = 10
a == b
#--> True
a is b
#--> True
10은 같은 객체임을 확인할 수 있다.
그렇다면, a를 수정하면 b 또한 수정되어야 하지 않을까?
a에 5를 더해도 b의 값은 변하지 않는다.
a = 10
b = 10
a += 5
a
#--> 15
b
#--> 10
b의 값은 변하지 않는다. 분명 같은 객체라고 했는데 왜 값이 변하지 않는지 의문이 들 수 있다. 필자 또한 그랬다.
이는 파이썬의 가변 객체와 불변 객체를 생각해 보면 이해하기 쉽다.
파이썬에서 int는 불변 객체이다. 즉 int 타입의 객체는 값이 변하지 않는 다는 것이다.
즉, 우리가 '+= 5'를 한 행위는 객체 값에 변화를 준게 아니다.
파이썬에서는 a가 참조하는 값이 10에서 15로 변한 것이다.
여기서 또 깨닫는 사실이 있다.
list_1 = [1,2,3]
list_2 = list_1
list_1[0] = 10
list_2
#--> [10,2,3]
필자는 이 구문을 이해하지 못하고 리스트를 복사하려면 얕은 복사(shallow copy), 깊은 복사(deep copy)가 필요하다고 단순하게 암기했었다.
하지만 앞의 개념을 적용시키면 이는 매우 당연하다.
list_1과 list_2는 같은 [1,2,3] 객체를 참조한다.
그리고 list는 가변 객체이다. 값이 변할 수 있다.
그래서 List_1[0] = 10 이 구문은 list_1이 다른 객체를 참조하도록 하는 구문이 아니라, list_1이 참조하는 객체 자체를 바꾼 것이다.
그래서 같은 객체를 참조하는 list_2의 출력값도 바뀌는 것이다.
'Python > Python' 카테고리의 다른 글
| 파이썬에서 Function과 method의 차이 (0) | 2023.03.20 |
|---|---|
| Python 에서의 Lambda method (0) | 2023.02.22 |
| Python에서 집합을 사용하는 이유 (0) | 2023.01.10 |
| 불변성과 문자열 수정 (0) | 2023.01.06 |
| 반내림 vs 내림(Python3) (0) | 2023.01.05 |
1. 다른 컬렉션의 중복을 제거할 때
집합에 아이템은 한 번만 저장될 수 있다. 그래서 다른 컬렉션의 중복을 제거하기 위해 사용될 수 있다.
다만, 집합에는 순서가 없기 때문에 아이템들의 순서가 바뀔 수 있다.
list_ = [1, 2, 2, 3, 3, 3, 4]
list_ = list(set(list_))
list_
#--==>> [1, 2, 3, 4]
2. 가변 객체들 간의 차이를 구할 때
집합은 리스트, 문자열, 가변 객체들 간의 차이를 구하고 싶을 때 사용될 수 있다.
다만, 여기서도 집합의 비정렬 특성으로 인해 결과의 순서는 원본과 다를 수 있다.
# 리스트의 차이
set([3, 5, 7]) - set([1, 2, 5])
#--==>> {3, 7}
# 문자열의 차이
set('abcd') - set('def')
#--==>>{'b', 'a', 'c'}
# 혼합 타입의 차이
set('abcd') - set(['a', 'b', 'f'])
#--==>> {'c', 'd'}
3. 순서에 상관없이 두 객체가 같은지 비교할 때
집합을 이용해 순서에 상관없이 두 객체가 같은지 비교할 수 있다.
예를 들어 같은 내용의 결과를 다른 순서로 생성할 경우 사용할 수 있다.
list_1, list_2 = [1, 2, 3, 4], [4, 3, 2, 1]
list_1 == list_2
#--==>> False
# 순서에 상관없는 비교
set(list_1) == set(list_2)
#--==>> True
# 정렬해서 비교
sorted(list_1) == sorted(list_2)
#--> True
# 문자열도 가능
str_1, str_2 = 'abc', 'bca'
str_1 == str_2
#--> False
set(str_1) == set(str_2)
#--> True
4. 같은 거대한 데이터를 다룰 때
집합은 DB 쿼리 결과와 같이 거대한 데이터를 다룰 때 편리하다.
# 커피를 좋아하는 사람
coffee = {'kim', 'lee', 'park', 'cho'}
# 차를 좋아하는 사람
tea = {'kim', 'park', 'koo', 'ki'}
# cho는 커피를 좋아하는가?
'cho' in coffee
#--> True
# 커피와 차 둘다 좋아하는 사람
coffee & tea
{'kim', 'park'}
# 모든 사람
coffee | tea
#--> {'koo', 'cho', 'ki', 'kim', 'lee', 'park'}
# 커피만 좋아하는 사람
coffee - tea
#--> {'lee', 'cho'}
# 커피를 좋아하는 모든 사람들은 차를 좋아하는가?(포함 집합)
coffee > tea
#--> False
# lee는 차를 좋아하는가?(부분 집합)
{'lee'} < tea
#--> False
# 둘 중에 하나만 좋아하는 사람
coffee ^ tea
#--> {'koo', 'ki', 'cho', 'lee'}'Python > Python' 카테고리의 다른 글
| Python 에서의 Lambda method (0) | 2023.02.22 |
|---|---|
| 참조에 의한 변수와 객체 연결 (0) | 2023.01.11 |
| 불변성과 문자열 수정 (0) | 2023.01.06 |
| 반내림 vs 내림(Python3) (0) | 2023.01.05 |
| 컴프리헨션 (0) | 2022.12.28 |
이 글은 파이썬 3 기준으로 작성되었다.
나누기 연산
/
'/' 연산자는 나머지도 포함된 일반적인 나누기를 수행한다.
//
'//' 연산자는 소수 나머지 부분을 잘라내고, 정수 피연산자에 대해서는 정수를 반환하며, 부동 소수점 피 연산자가 하나라도 있는 경우에는 부동 소수점 수를 반환하는 반내림(Floor)를 수행한다.
내림 vs 버림
// 연산자는 비공식적으로 버림(truncating) 나누기라고 불리지만, 내림(Floor)나누기 라고 부르는 것이 더 정확하다. // 연산자는 낮은 값을 기준으로 나눈 결괏값의 소수 부분을 잘라낸다. 즉 / 나누기 결과에서 가까운 낮은 정수값을 의미한다.
이는 단순히 소수 부분을 잘라내는 것과는 차이가 존재한다. 특히 음수 값에 적용될 때 더 중요하다.
이 차이는 math 모듈을 사용하여 확인할 수 있다.
import math
# 낮은 값 중에서 가장 가까운 수
math.floor(2.5)
#--==>> 2
math.floor(-2.5)
#--==>> -3
# (0을 향해서) 소수 부분 잘라 내기
math.trunc(2.5)
#--==>> 2
math.trunc(-2.5)
#--==>> -2
5 / 2, 5 / -2
#--==>> (2.5, -2.5)
5 // 2, 5 // -2
#--==>> (2, -3)
'Python > Python' 카테고리의 다른 글
| Python에서 집합을 사용하는 이유 (0) | 2023.01.10 |
|---|---|
| 불변성과 문자열 수정 (0) | 2023.01.06 |
| 컴프리헨션 (0) | 2022.12.28 |
| __name__ (0) | 2022.11.16 |
| 파이썬(Python), 파이참(PyCharm) 설치(windows) (0) | 2021.07.24 |
if __name__ == "__main__"
이 구문을 단순하게 파이썬 파일 실행을 위한 구문이라고 외우기만 했었는데 __name__ 변수의 의미를 알면 이해가 되는 구문이어서 __name__ 변수에 대해 정리해보았다.
__name__의 의미를 알기 위해서는 모듈과 스크립트를 알아야 해 아래에 간단하게 정리했다.
모듈과 스크립트
모듈과 스크립트 모두 파이썬 파일(.py)을 의미한다. 그렇지만 이 둘은 용도로 구분된다.
프로그램에서 필요한 변수들이나 함수들을 정의해 놓는 용도의 파일은 모듈이고, 실제 프로그램을 작동시키는 코드를 담은 용도의 파일은 스크립트이다. 즉, 모듈은 import 용도의 파일이고, 스크립트는 실행 용도의 파일이다.
아래의 예에서 area.py는 모듈이고 run.py는 스크립트이다.
area.py
def triangle(height, base):
"""직각 삼각형의 넓이를 구하는 함수"""
return height * base / 2
run.py
import area
height = 5
base = 3
result = area.triangle(height, base)
print("밑변이 {}이고 높이가 {}인 삼각형의 면적은 {}입니다.".format(height, base, result))
__name__
__name__은 모듈의 이름을 저장하는 특수 변수이다.
__name__이 내 파일에서 실행되면 __main__으로 설정되고 다른 파일에서 임포트 당하여 실행되면 모듈 이름으로 설정된다. 아래 예시를 보면
area.py
print("area 모듈 이름: {}".format(__name__))
#--==>>area 모듈 이름: __main__
area파일에서 실행된 __name__ 변수는 __main__이지만
run.py
print("run 모듈 이름: {}".format(__name__))
#--==>> run 모듈 이름: __main__
import area
#--==>> area 모듈 이름: area
run.py파일에서 실행된 area.py의 __name__변수는 area로 출력된다.
if __name__ == “__main__”
즉, 이 구문은 __name__ 변수가 현재 __main__이라면 실행하라는 구문이다. 해당 파일에서만 실행하고 싶은 코드는 이 조건문 안에 넣어주면 된다.
area.py
def triangle(height, base):
"""직각 삼각형의 넓이를 구하는 함수"""
return height * base / 2
if __name__ == "__main__":
print(triangle(1, 2) == 1)
#--==>> True
run.py
import area
height = 5
base = 3
result = area.triangle(height, base)
print("밑변이 {}이고 높이가 {}인 삼각형의 면적은 {}입니다.".format(height, base, result))
이 예시에서 area.py파일에서만 True가 출력되는 것을 확인할 수 있다.
main()
area.py
def triangle(height, base):
"""직각 삼각형의 넓이를 구하는 함수"""
return height * base / 2
def main():
"""함수를 테스팅하는 메인 함수"""
print(triangle(1, 2) == 1)
if __name__ == "__main__":
main()
#--==>> True
이렇게 간단하게 정리할 수 있다.

부족하거나 잘못된 내용이 있을 경우 댓글 달아주시면 감사하겠습니다.
이 글에 부족한 부분이 존재할 경우 추후에 수정될 수 있습니다.
'Python > Python' 카테고리의 다른 글
| Python에서 집합을 사용하는 이유 (0) | 2023.01.10 |
|---|---|
| 불변성과 문자열 수정 (0) | 2023.01.06 |
| 반내림 vs 내림(Python3) (0) | 2023.01.05 |
| 컴프리헨션 (0) | 2022.12.28 |
| 파이썬(Python), 파이참(PyCharm) 설치(windows) (0) | 2021.07.24 |