[파이썬] 파이썬은 모든것이 객체다
파이썬은 모든것이 객체다
파이썬에선 모든것이 객체라는 말이 있다. 이게 무슨 말인지 모르더라도 파이썬을 사용하는데 큰 문제는 없다. 하지만 좀더 깊게 들어가고 싶다면 한번쯤 공부해보고 가는 것이 좋다.
우선 아래 코드를 실행하면
class A:
pass
a = A()
print(type(a)) # <class '__main__.A'>
class A 라고 출력된다. 변수 a 는 A 라는 클래스의 객체이기 때문이다.
그런데 배열과 정수, 문자열에 대해서도 동일하게 출력해보면, 타입 정보와 함께 앞에 class 가 붙여서 나온다.
print(type([1,2,3,4])) # <class 'list'>
print(type(5)) # <class 'int'>
print(type("1234")) # <class 'str'>
심지어 추가한 함수와 len 처럼 빌트인 함수도 클래스의 일종이다.
def foo():
pass
print(type(foo)) # <class 'function'>
print(type(len)) # <class 'builtin_function_or_method'>
파이썬에서는 모든것이 객체라는 말은 일반적인 클래스 인스턴스 뿐만 아니라 정수, 배열, 문자열 그리고 함수까지도 클래스에서 생성된 객
체중에 하나라는 것을 뜻한다. 파이썬은 모든 것을 클래스의 일종인 객체로 만들어서 관리하고 있다.
변수의 역할
객체는 메모리에 상주하는 하나의 형태다. 그리고 변수는 메모리에 상주하는 객체를 가리키는 포인터로 쓰인다.
예를 들어 아래코드 변수 a 는 100 이라는 객체의 위치 값을 가르키고 있기 때문에 100 이라는 값을 출력한다. id 라는 함수를 이용해서 객체의 주소지를 확인할 수 있는데 아래 코드처럼 100 의 주소값과 변수 a 의 주소값이 동일하다.
a = 100
print(id(100)) # 4310453584
print(id(a)) # 4310453584
mutable/immutable object
객체는 값을 변경할 수 있는 mutable 과 변경할 수 없는 immutable 로 나눈다.
- mutable 타입에는 정수, 실수, 문자열, 튜플, 불린 처럼 primitive 타입이 해당하고
- immutable 타입에는 리스트, 딕셔너리, 집합, 사용자 정의 객체가 해당한다
mutable과 immutable 은 다룰때 주의가 필요한 부분인데 직접 예시를 보면서 공부해보자.
아래 코드를 실행하면 a 는 10을 갖게 된다
a = 10
a += 1
원래 모든 것이 객체이기 때문에 10 이라는 객체에서 값이 11로 변했어야 정상이다.
그런데 정수 객체는 immutable 객체이기 때문에 변하지 않는다. 그러면 뭐가 바뀌느냐? a 가 참조하고 있는 객체가 바뀐다. 기존에는 10 을 갖고 있는 객체를 참조하고 있었다면 지금은 11을 갖고 있는 객체를 참조하게 된다. 그래서 전후로 참조하고 있는 메모리주소를 확인해보면 출력값이 달라지는걸 확인할 수 있다
a = 10
print(id(a)) # 4365632016
a += 10
print(id(a)) # 4365632336
그런데 immutable 객체인 리스트의 경우 수정 전수 메모리 주소는 동일하다.
a = []
print(id(a)) # 4339166912
a.append(1)
print(id(a)) # 4339166912
리스트는 mutable 객체이기 때문에 메모리 주소가 변경되지 않고 직접 객체의 값을 변경한다.
함수 인자 사용시 주의점
함수 인자로 전달하는 경우 객체의 mutable/immuatable 요소 차이에 따라서 결과값이 달라진다. 아래 코드에선 add_int 함수에서 전달받은 인자에 값을 10만큼 더해주고 있다.
def add_int(arg):
arg += 10
a = 10
add_int(a)
print(a) # 10 출력
하지만 결과 값은 그대로 10으로 동일하다. a 의 결과값은 바뀌지 않는다. 이유는 정수가 immutable 객체이기 때문이다.
add_int 함수 안에서 함수의 인자 arg 는 10의 주소를 가르키고 있지만 10을 더하면서 다른 주소를 가르키게 된다. a 와 arg 각각이 다른 주소를 참조하고 있기 때문에 결과 값이 다르다.
그런데 배열을 인자로 넣는 경우엔 양상이 다르다
def add_array(arg):
arg += [10]
b = []
add_array(b)
print(b) # [10] 출력
위 코드를 실행하면 빈 배열이 아니라 10이 추가된 값으로 나온다. 이유는 배열이 mutable 객체이기 때문이다.
add_array 함수 안에 있는 배열 arg 는 내부에서 더하기 연산을 해도 기존과 동일한 주소를 가르키고 객체의 값을 변경시킨다. 그래서 원래는 빈 배열만 있었던 메모리가 [10] 으로 바뀌게 된다