변수는 Value의 이름표, 함수는 Code의 이름표
1.
def hello():
print("hello")
hello()
def hello():
print("hello")
f= hello
f()
1과 2는 동일하게 함수 hello를 불러오는 온다.
1과 2 차이점은 f = hello 의 부분이다.
🟩 f = hello
여기서 hello()처럼 괄호가 없기 때문에 함수 실행이 아니라 함수 자체를 참조합니다.
hello라는 함수 객체를 f라는 변수에 할당하는 것이다.
즉, f는 이제 hello 함수와 동일한 기능을 갖는 함수 객체가 됩니다.

class Func:
def __call__(self):
print("call")
f = Func()
f()
여기서 질문?)
❓1. f= hello 와 f = Func() 의 다른점이 무엇인가?
❓2. call 은 무엇인가?
🟩f = hello
hello는 함수 객체,
f는 그 함수를 참조하는 변수.
🟩f = Func()
Func는 클래스,
f는 Func 클래스의 인스턴스(== 객체)
클래스 자체는 기본적으로 함수처럼 호출할 수 없음
하지만 call()을 정의해주면, 함수처럼 f() 호출 가능
def print_num(a,b,c):
print(a,b,c)
#1.
print_num(*[7,8,9]) #7 8 9
#2.
print_num(*(7,8,9)) #7 8 9
#3.
x = [7,8,9]
print_num(*x) #7 8 9
리스트,튜플 앞에 *(asterisk) 를 붙여서 자동으로 언패킹 되어서 전달되며 함수의 인수 a,b,c에 차례로 값이 할당된다.
def foo(*a):
print(a)
foo(1,2,3) # (1, 2, 3)
foo(1,2,3,4) # (1, 2, 3, 4)
*a foo함수 호출로부터 서로 다른 개수의 인자를 전달한다.
def foo(**a):
print(a)
foo(a=1,b=2,c=3) #{'a': 1, 'b': 2, 'c': 3}
foo(a=1,b=2,c=3,d=4) #{'a': 1, 'b': 2, 'c': 3, 'd': 4}
키워드 가변인자는 딕셔너리가 출력된다
# 키워드 가변인자 + 위치 가변인자
def foo(*a,**b):
print(a)
print(b)
foo(1,2,3,a=1,b=2,c=3)
#(1, 2, 3)
#{'a': 1, 'b': 2, 'c': 3}
lambda함수 : 간단한 함수를 한 줄로 작성할 수 있게 해주는 간단한 문법입니다.
def add(x, y):
return x + y
add_lambda = lambda x, y: x + y
print(add(3, 5)) #8
print(add_lambda(3, 5)) #8
네 가지 이름공간(namespace)의 앞 글자를 딴 것으로, 안쪽에서 바깥쪽으로 순서대로 탐색한다.
| 이름공간 | 설명 | 예시 |
|---|---|---|
| Local | 현재 함수 안의 지역변수 | 함수 내부에서 정의된 변수 |
| Enclosing | 바깥 함수의 지역변수 (중첩함수) | 클로저에서 바깥 함수의 변수 |
| Global | 모듈 전체에서 정의된 변수 | 함수 밖에서 정의된 변수 |
| Built-in | 파이썬 내장함수/변수 | print, len, range 등 |
Local: 현재 함수 내부에서 먼저 찾음
Enclosing: 함수가 중첩되어 있다면, 바깥 함수의 변수 확인
Global: 전역 변수에서 찾음
Built-in: 파이썬 기본 제공 함수/이름에서 찾음.
x = "global"
def outer():
x = "enclosing"
def inner():
x = "local"
print(x) # LEGB에 따라 local 찾음
inner()
outer()
출력값 : local
x = "global"
def outer():
x = "enclosing"
def inner():
print(x)
inner()
outer()
출력값 : enclosing
local에 해당되는 함수가 없으므로, Enclosing 조건에 들어간다.
[print(x)]
▲
├─ Local → inner() 함수 내부
├─ Enclosing → outer() 함수 내부
├─ Global → 파일 상단 전역 변수
└─ Built-in → 파이썬 기본 제공 함수
def calc():
a = 3
b = 5
def mul_add(x):
return a * x + b # 함수 바깥쪽에 있는 지역 변수 a, b를 사용하여 계산
return mul_add # mul_add 함수를 반환
c = calc()
print(c(1), c(2), c(3), c(4), c(5))
결과 값 : 8 11 14 17 20
calc가 끝났는데도 c는 calc의 지역 변수 a, b를 사용해서 계산을 하고 있다.
이렇게 함수를 둘러싼 환경으로 계속 유지하다가, 함수를 호출할때 다시 꺼내서 함수를 사용하는 것을 클로저(closure) 라고 한다.
c에 저장된 함수가 클로저다.

[출처:파이썬 코딩 도장]
정의: 객체를 만들기 위한 설계도 또는 틀.
예: 자동차를 만들기 위한 설계도. 설계도 자체는 달리지 않지만, 설계도를 기반으로 실제 자동차(객체)를 만들 수 있음.
class Car:
def drive(self):
print("달립니다.")
정의: 클래스로부터 객체(인스턴스)를 만들 때 자동으로 호출되는 메서드.
객체를 만들자마자 초기값을 설정해주는 역할.
class Car:
def __init__(self, color):
self.color = color # 인스턴스 변수 생성
print("자동차가 만들어졌습니다.")
def drive(self):
print(f"{self.color} 자동차가 달립니다.")
정의: 클래스를 기반으로 실제로 만들어진 객체.
클래스는 설계도, 인스턴스는 설계도를 바탕으로 실제 만든 제품.
my_car = Car("빨간색") # → 여기서 Car는 클래스, my_car는 인스턴스
my_car.drive()
| 개념 | 역할 | 예시 |
|---|---|---|
| 클래스 | 설계도 | class Car: |
| 생성자 | 객체 초기화 | def __init__(self, color): |
| 인스턴스 | 클래스 기반으로 생성된 객체 | my_car = Car("빨간색") |
hasattr(객체, '속성명')
객체: 속성을 검사할 대상 객체
속성명: 문자열 형태로 속성 이름을 전달
🟩 반환값
True → 해당 속성이 객체에 존재할 경우
False → 해당 속성이 객체에 존재하지 않을 경우
class Person:
def __init__(self, name):
self.name = name
def greet(self):
print(f"Hi, I'm {self.name}")
p = Person("goorm")
print(hasattr(p, 'name')) # True
print(hasattr(p, 'greet')) # True
print(hasattr(p, 'age')) # False
hasattr(p, 'greet')도 True를 반환하는 이유는, 메서드 또한 속성으로 취급되기 때문이다.
✅ 언제 사용하나요?
if hasattr(p, 'name'):
print(p.name)
else:
print("이름 속성이 없습니다.")
✅ 참고: getattr()과 함께 쓰는 예
value = getattr(p, 'age', '나이 정보 없음')
print(value) # → '나이 정보 없음'
getattr()은 속성이 없을 경우, 세 번째 인자를 기본값으로 반환해 줍니다.