함수 호출 시 필요한 인자의 개수가 정해져있지 않음
*args)def func1(*args)
print(args)
func1(1,2,3)
func1(1,2,3,4,5)
결과:
(1, 2, 3)
(1, 2, 3, 4, 5)
**kwargs)def func2(**kwargs)
print(kwargs)
func2(a=1,b=2,c=3)
func2('book'=10, 'iPhone'=2000, 'coffee'=4)
결과:
{'a':1, 'b':2, 'c':3}
{'book':10, 'iPhone':2000, 'coffee':4}
*args + **kwargsdef func3(*args, **kwargs)
print(args)
print(kwargs)
func3(1,2,4=8,5=10)
(1, 2)
{4:8, 5:10}
def 키워드가 아닌 lambda 키워드로 정의된 익명의 함수
lambda arguments: expression
# 두 수의 합을 계산하는 lambda 함수
add = lambda x, y: x + y
print(add(3, 5)) # → 8
# 리스트를 제곱값으로 변환
squares = list(map(lambda x: x**2, [1, 2, 3, 4]))
# → [1, 4, 9, 16]
data = [('apple', 2), ('banana', 5), ('cherry', 1)]
# 두 번째 요소로 오름차순 정렬
sorted_data = sorted(data, key=lambda item: item[1])
# → [('cherry', 1), ('apple', 2), ('banana', 5)]
# 짝수만 걸러내기
evens = list(filter(lambda x: x % 2 == 0, range(10)))
# → [0, 2, 4, 6, 8]
def 함수와의 차이| 항목 | def 함수 | lambda 함수 |
|---|---|---|
| 이름(Name) | 반드시 이름을 가짐 | 이름이 없거나(익명), 변수에 할당 가능 |
| 본문(Body) | 여러 줄 작성 가능 | 한 줄의 표현식만 가능 |
| 가독성 | 복잡한 로직에 적합 | 간단한 로직에 적합 |
| 반환(return) | return 키워드 사용 | 표현식 결과 자동 반환 |
장점
단점
<lambda>가 뜨므로 위치 파악이 다소 힘들 수 있음lambda 함수는 “한 줄짜리, 익명 함수”map, filter, sorted 등의 인자로 쓰일 때 유용def 함수를 사용해 가독성을 유지하는 것이 좋다.파이썬에서의 변수 참조 규칙
L : Local
<
E : Enclosed function locals
<
G : Global
<
B : Built-in
global 키워드Local 영역 내에서 Global 변수를 사용하려면
global 키워드를 이용해 해당 변수가 Global 변수임을 선언한다.
a = 10
def test():
global a
a = 20
test()
print(a)
결과:
20
def outer():
num = 3
def inner():
print(num)
return inner
f = outer()
f()
결과:
3
inner()는 num을 참조할 수 있을까?파이썬은 클로저(Closure)를 지원하는 언어이기 때문
함수가 자신이 정의될 때의 "외부 스코프 변수들"을 기억하고 참조할 수 있는 함수
즉, 함수가 return 되어도 그 함수가 정의될 당시의 환경(변수 상태)을 함께 묶어서 __closure__ 속성에 튜플 형태로 저장해둔 것
print(f.__closure__[0].cell_contents)
결과:
3
outer()가 호출되면 로컬 변수 num = 3이 생성됨inner() 함수는 num이라는 이름을 자신 내부가 아니라 바깥(outer)의 스코프에서 찾음outer()는 inner() 함수를 반환하면서 그 때의 num = 3 상태도 기억된 함수 객체가 f에 저장됨f()를 호출하면 inner()가 실행되면서 여전히 num = 3을 알고 있어서 출력 가능함outer() 호출
├── num = 3
└── inner() 정의
└── 내부에서 num을 사용 ← 이 num은 outer 스코프의 num을 참조함
f = outer() 호출 결과인 inner()
f() → inner() 실행, 이때 num = 3을 기억하고 있음
inner 함수는 정의될 당시의 환경(outer의 지역 변수들)을 기억하고 있으므로 num을 참조할 수 있다.
클로저는 다음과 같은 상황에 유용:
✔️ 상태를 기억하는 함수 만들기
✔️ 데코레이터 구현
✔️ 캡슐화된 함수형 프로그래밍
__getattribute__ & hasattr() & getattr()__getattribute__ : magic methodclass Car:
def __getattribute__(self, item):
print(item, '객체에 접근하였습니다.')
def __init__(self):
self.wheel = 4
def drive(self):
print("drive~")
myCar = Car()
myCar.nothing
결과:
nothing객체에 접근하였습니다.
hasattr(object, name)hasattr(myCar, 'nothing')
hasattr(myCar, 'wheel')
결과:
False
True
getattr(object, name[, default])newDrive = getattr(myCar, 'drive')
newDrive()
결과:
drive~
추상 클래스(Abstract Class)는 상속을 통해서만 사용 가능한 클래스이며,
자식 클래스가 반드시 구현해야 할 메서드(추상 메서드)를 정의하는 데 사용됩니다.
Python에서는 abc(Abstract Base Class) 모듈을 사용합니다.
from abc import ABC, abstractmethod
class Animal(ABC): # ABC를 상속받아야 추상 클래스가 됨
@abstractmethod
def speak(self):
pass
a = Animal() # TypeError: Can't instantiate abstract class Animal with abstract methods speak
class Dog(Animal):
def speak(self):
return "Woof!"
d = Dog()
print(d.speak())
결과:
Woof!
| 특징 | 설명 |
|---|---|
| 직접 인스턴스화 불가 | 추상 메서드가 하나라도 있으면 Animal()처럼 직접 못 씀 |
| 자식 클래스가 구현 | 추상 메서드를 반드시 자식 클래스에서 구현해야 함 |
| 인터페이스 제공 | "이런 기능이 필요하다"는 계약(Contract) 역할 |
| 공통 로직 포함 가능 | 추상 클래스 안에 실제 구현된 메서드도 포함 가능 |