KR_Function - somaz94/python-study GitHub Wiki
ํจ์๋ ํน์ ์์ ์ ์ํํ๋ ์ฝ๋์ ๋ธ๋ก์ผ๋ก, ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๋ชจ๋ํ๋ฅผ ์ํด ์ฌ์ฉ๋๋ค.
# ๊ธฐ๋ณธ ํจ์ ๊ตฌ์กฐ
def ํจ์์ด๋ฆ(๋งค๊ฐ๋ณ์):
์คํํ _์ฝ๋
return ๋ฐํ๊ฐ
# ์์
def greet(name):
return f"Hello, {name}!"
# 1. ๋งค๊ฐ๋ณ์์ ๋ฐํ๊ฐ์ด ๋ชจ๋ ์๋ ํจ์
def add(a, b):
return a + b
# 2. ๋งค๊ฐ๋ณ์๋ง ์๋ ํจ์
def print_info(name, age):
print(f"์ด๋ฆ: {name}, ๋์ด: {age}")
# 3. ๋ฐํ๊ฐ๋ง ์๋ ํจ์
def get_pi():
return 3.14
# 4. ๋งค๊ฐ๋ณ์์ ๋ฐํ๊ฐ์ด ๋ชจ๋ ์๋ ํจ์
def say_hello():
print("Hello!")
# *args: ์ฌ๋ฌ ๊ฐ์ ์์น ์ธ์๋ฅผ ํํ๋ก ๋ฐ์
def sum_all(*args):
return sum(args)
# **kwargs: ํค์๋ ์ธ์๋ฅผ ๋์
๋๋ฆฌ๋ก ๋ฐ์
def print_kwargs(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Alice")) # Hello, Alice!
print(greet("Bob", "Hi")) # Hi, Bob!
# ์ผ๋ฐ ํจ์
def add(a, b):
return a + b
# ๋๋ค ํจ์
add = lambda a, b: a + b
# ํ์ฉ ์์
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
# ์ ์ญ ๋ณ์
global_var = 10
def function():
# ์ง์ญ ๋ณ์
local_var = 20
print(global_var) # ์ ์ญ ๋ณ์ ์ ๊ทผ ๊ฐ๋ฅ
# ์ ์ญ ๋ณ์ ์์
global global_var
global_var = 30
โ ํจ์ ์์ฑ Tip:
- ํจ์๋ ํ ๊ฐ์ง ์์ ๋ง ์ํํ๋๋ก ์ค๊ณ
- ํจ์ ์ด๋ฆ์ ๊ธฐ๋ฅ์ ๋ช ํํ ํํ
- ๋ฌธ์ํ ๋ฌธ์์ด(docstring) ์ฌ์ฉ
- ์ ์ ํ ๋งค๊ฐ๋ณ์์ ๋ฐํ๊ฐ ์ค๊ณ
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ํจ์๋ฅผ ์ผ๊ธ ๊ฐ์ฒด๋ก ์ทจ๊ธํ๊ณ ๋ถ๋ณ์ฑ๊ณผ ์์ ํจ์๋ฅผ ์ค์์ํ๋ ํจ๋ฌ๋ค์์ด๋ค.
# ์์ ํจ์
def pure_add(a, b):
return a + b # ์ธ๋ถ ์ํ ๋ณ๊ฒฝ ์์, ๋์ผ ์
๋ ฅ = ๋์ผ ์ถ๋ ฅ
# ๊ณ ์ฐจ ํจ์: ํจ์๋ฅผ ์ธ์๋ก ๋ฐ๊ฑฐ๋ ํจ์๋ฅผ ๋ฐํ
def apply_operation(a, b, operation):
return operation(a, b)
result = apply_operation(5, 3, lambda x, y: x + y) # 8
# ํจ์ํ ๋๊ตฌ
from functools import reduce
# map: ๊ฐ ์์์ ํจ์ ์ ์ฉ
numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers)) # [2, 4, 6, 8, 10]
# filter: ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์์๋ง ํํฐ๋ง
evens = list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4]
# reduce: ๋์ ์ง๊ณ
total = reduce(lambda acc, x: acc + x, numbers, 0) # 15
ํด๋ก์ ๋ ์์ ์ ๊ฐ์ธ๋ ์ค์ฝํ์ ๋ณ์๋ฅผ ๊ธฐ์ตํ๋ ํจ์์ด๋ค.
def make_counter():
count = 0 # ๋ด๋ถ ๋ณ์
def counter():
nonlocal count # ์ธ๋ถ ํจ์์ ๋ณ์ ์ฌ์ฉ
count += 1
return count
return counter # ๋ด๋ถ ํจ์ ๋ฐํ
# ์ฌ์ฉ ์์
counter = make_counter()
print(counter()) # 1
print(counter()) # 2
print(counter()) # 3
# ํด๋ก์ ๋ก ํจ์ ํฉํ ๋ฆฌ ๋ง๋ค๊ธฐ
def power_factory(exponent):
def power(base):
return base ** exponent
return power
square = power_factory(2)
cube = power_factory(3)
print(square(4)) # 16
print(cube(3)) # 27
๋ฐ์ฝ๋ ์ดํฐ๋ ๊ธฐ์กด ํจ์์ ๋์์ ์์ ํ๊ฑฐ๋ ํ์ฅํ๋ ์ค๊ณ ํจํด์ด๋ค.
# ๊ธฐ๋ณธ ๋ฐ์ฝ๋ ์ดํฐ
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"ํจ์ {func.__name__} ์คํ ์์")
result = func(*args, **kwargs)
print(f"ํจ์ {func.__name__} ์คํ ์๋ฃ")
return result
return wrapper
# ๋ฐ์ฝ๋ ์ดํฐ ์ ์ฉ
@log_decorator
def greet(name):
return f"Hello, {name}!"
# ์ ์ฝ๋๋ ๋ค์๊ณผ ๋์ผ:
# greet = log_decorator(greet)
print(greet("Alice")) # ๋ก๊ทธ ์ถ๋ ฅ ํ "Hello, Alice!" ๋ฐํ
# ์ธ์๋ฅผ ๋ฐ๋ ๋ฐ์ฝ๋ ์ดํฐ
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
results = []
for _ in range(times):
results.append(func(*args, **kwargs))
return results
return wrapper
return decorator
@repeat(3)
def say_hi():
return "Hi!"
print(say_hi()) # ["Hi!", "Hi!", "Hi!"] ๋ฐํ
์ฌ๊ท ํจ์๋ ์๊ธฐ ์์ ์ ํธ์ถํ๋ ํจ์๋ก, ๋ณต์กํ ๋ฌธ์ ๋ฅผ ๋จ์ํํ ์ ์๋ค.
# ํฉํ ๋ฆฌ์ผ ๊ณ์ฐ
def factorial(n):
if n <= 1: # ๊ธฐ์ ์กฐ๊ฑด(base case)
return 1
return n * factorial(n - 1) # ์ฌ๊ท ํธ์ถ
print(factorial(5)) # 120
# ํผ๋ณด๋์น ์์ด
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(6)) # 8
# ๊ผฌ๋ฆฌ ์ฌ๊ท ์ต์ ํ
def factorial_tail(n, acc=1):
if n <= 1:
return acc
return factorial_tail(n - 1, n * acc)
print(factorial_tail(5)) # 120
์ ๋๋ ์ดํฐ๋ ์ดํฐ๋ ์ดํฐ๋ฅผ ์์ฑํ๋ ํจ์๋ก, ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ ์ธ ๋ฐ์ดํฐ ์์ฑ์ ์ ์ฉํ๋ค.
# ์ ๋๋ ์ดํฐ ํจ์
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
# ์ฌ์ฉ
counter = count_up_to(5)
print(next(counter)) # 1
print(next(counter)) # 2
# for ๋ฃจํ์์ ์ฌ์ฉ
for num in count_up_to(3):
print(num) # 1, 2, 3 ์ถ๋ ฅ
# ์ ๋๋ ์ดํฐ ํํ์
squares = (x**2 for x in range(5))
print(list(squares)) # [0, 1, 4, 9, 16]
# ๋ฌดํ ์ํ์ค ์์ฑ
def infinite_sequence():
num = 0
while True:
yield num
num += 1
counter = infinite_sequence()
for i in range(5):
print(next(counter)) # 0, 1, 2, 3, 4 ์ถ๋ ฅ
Python 3.5๋ถํฐ ๋์ ๋ ํ์ ํํธ๋ฅผ ํตํด ํจ์ ์ธ์์ ๋ฐํ๊ฐ์ ํ์ ์ ๋ช ์ํ ์ ์๋ค.
# ๊ธฐ๋ณธ ํ์
ํํธ
def greeting(name: str) -> str:
return f"Hello, {name}!"
# ๋ณตํฉ ํ์
from typing import List, Dict, Tuple, Optional, Union, Callable
def process_items(items: List[int]) -> List[int]:
return [item * 2 for item in items]
def merge_dicts(dict1: Dict[str, int], dict2: Dict[str, int]) -> Dict[str, int]:
return {**dict1, **dict2}
# ์ ํ์ ๋งค๊ฐ๋ณ์
def find_user(user_id: int, full_info: Optional[bool] = None) -> Dict[str, Union[str, int]]:
user = {"id": user_id, "name": "John Doe"}
if full_info:
user["email"] = "[email protected]"
return user
# ํจ์ ํ์
def apply_transformation(items: List[int], transform: Callable[[int], int]) -> List[int]:
return [transform(item) for item in items]
result = apply_transformation([1, 2, 3], lambda x: x * x)
๋ถ๋ถ ์ ์ฉ๊ณผ ์ปค๋ง์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์์ ํจ์์ ์ผ๋ถ ์ธ์๋ฅผ ๋ฏธ๋ฆฌ ์ฑ์๋ฃ๋ ๊ธฐ๋ฒ์ด๋ค.
from functools import partial
# ๋ถ๋ถ ์ ์ฉ
def multiply(a, b, c):
return a * b * c
# ์ฒซ ๋ฒ์งธ ์ธ์๋ง ๊ณ ์
double = partial(multiply, 2)
print(double(3, 4)) # 2 * 3 * 4 = 24
# ๋ ๋ฒ์งธ ์ธ์๊น์ง ๊ณ ์
double_triple = partial(multiply, 2, 3)
print(double_triple(4)) # 2 * 3 * 4 = 24
# ์ปค๋ง ์ง์ ๊ตฌํ
def curry(func):
def curried(*args, **kwargs):
if len(args) + len(kwargs) >= func.__code__.co_argcount:
return func(*args, **kwargs)
return lambda *more_args, **more_kwargs: curried(*(args + more_args), **{**kwargs, **more_kwargs})
return curried
@curry
def add3(a, b, c):
return a + b + c
add1 = add3(1)
add1_2 = add1(2)
print(add1_2(3)) # 1 + 2 + 3 = 6
print(add3(1)(2)(3)) # 1 + 2 + 3 = 6
print(add3(1, 2, 3)) # 1 + 2 + 3 = 6
ํจ์๋ฅผ ์ฌ์ฉํด ์ปจํ ์คํธ ๊ด๋ฆฌ์๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ด๋ค.
from contextlib import contextmanager
import time
# ์ปจํ
์คํธ ๊ด๋ฆฌ์ ํจ์
@contextmanager
def timer():
start = time.time()
try:
yield # ์ด ์ง์ ์์ with ๋ธ๋ก ๋ด๋ถ ์ฝ๋ ์คํ
finally:
end = time.time()
print(f"์คํ ์๊ฐ: {end - start:.5f}์ด")
# ์ฌ์ฉ ์์
with timer():
# ์๊ฐ์ ์ธก์ ํ ์ฝ๋
result = sum(i**2 for i in range(10000))
# ๋ฆฌ์์ค ๊ด๋ฆฌ๋ฅผ ์ํ ์ปจํ
์คํธ ๊ด๋ฆฌ์
@contextmanager
def open_file(filename, mode='r'):
try:
f = open(filename, mode)
yield f
finally:
f.close()
# ์ฌ์ฉ ์์
with open_file('example.txt', 'w') as f:
f.write('Hello, World!')
Python 3.5๋ถํฐ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ํ async/await ๊ตฌ๋ฌธ์ด ๋์ ๋์๋ค.
import asyncio
# ๋น๋๊ธฐ ํจ์ ์ ์
async def fetch_data(url):
print(f"{url} ๋ฐ์ดํฐ ์์ฒญ ์ค...")
await asyncio.sleep(1) # ๋น๋๊ธฐ ๋๊ธฐ (I/O ์์
์๋ฎฌ๋ ์ด์
)
return f"{url}์ ๋ฐ์ดํฐ"
# ์ฌ๋ฌ ๋น๋๊ธฐ ์์
์คํ
async def fetch_all():
urls = [
"https://example.com/api/1",
"https://example.com/api/2",
"https://example.com/api/3"
]
# ๋์ ์คํ
tasks = [fetch_data(url) for url in urls]
results = await asyncio.gather(*tasks)
return results
# ๋น๋๊ธฐ ๋ฉ์ธ ํจ์
async def main():
results = await fetch_all()
for result in results:
print(result)
# ์คํ
if __name__ == "__main__":
asyncio.run(main())
# ๋น๋๊ธฐ ์ ๋๋ ์ดํฐ
async def async_generator():
for i in range(5):
await asyncio.sleep(0.1)
yield i
# ๋น๋๊ธฐ ์ดํฐ๋ ์ด์
async def use_async_gen():
async for value in async_generator():
print(value)
ํจ์ ์ฑ๋ฅ์ ๊ฐ์ ํ๋ ๋ค์ํ ์ต์ ํ ๊ธฐ๋ฒ์ด๋ค.
import time
import functools
# 1. ๋ฉ๋ชจ์ด์ ์ด์
(Memoization) - ์ฌ๊ท ํจ์ ์ต์ ํ
@functools.lru_cache(maxsize=None)
def fibonacci_memo(n):
if n <= 1:
return n
return fibonacci_memo(n - 1) + fibonacci_memo(n - 2)
# ์ฑ๋ฅ ๋น๊ต
def fibonacci_normal(n):
if n <= 1:
return n
return fibonacci_normal(n - 1) + fibonacci_normal(n - 2)
start = time.time()
fibonacci_normal(30)
print(f"์ผ๋ฐ ์ฌ๊ท: {time.time() - start:.5f}์ด")
start = time.time()
fibonacci_memo(30)
print(f"๋ฉ๋ชจ์ด์ ์ด์
: {time.time() - start:.5f}์ด")
# 2. ์ ๋๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ
def read_large_file(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line.strip()
# 3. ์ง์ญ ๋ณ์ ์ต์ ํ
def process_items_optimized(items):
# ์ง์ญ ๋ณ์์ ํจ์ ๋ฐ์ธ๋ฉ
_len = len
result = []
_append = result.append
for item in items:
_append(_len(str(item)))
return result
# 4. ์ธ๋ผ์ธ ํจ์ ํธ์ถ ์ต์ ํ
def calculate_sum(numbers):
# ํจ์ ํธ์ถ ๋์ ์ธ๋ผ์ธ ๊ณ์ฐ
total = 0
for num in numbers:
total += num
return total
์ค๋ฌด์์ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ ํจ์ ๋์์ธ ํจํด์ด๋ค.
# ๊ฐ์ฒด ์์ฑ์ ์บก์ํํ๋ ํฉํ ๋ฆฌ ํจ์
def create_person(name, age, profession=None):
person = {
'name': name,
'age': age
}
if profession:
person['profession'] = profession
if age < 18:
person['category'] = 'minor'
else:
person['category'] = 'adult'
return person
# ์ฌ์ฉ ์์
student = create_person("Alice", 15)
developer = create_person("Bob", 28, "Software Developer")
# ๋ค์ํ ์ ๋ต ํจ์
def discount_regular(order_total):
return order_total * 0.05 # 5% ํ ์ธ
def discount_premium(order_total):
return order_total * 0.1 # 10% ํ ์ธ
def discount_vip(order_total):
return max(order_total * 0.15, 100) # 15% ํ ์ธ, ์ต์ 100
# ์ ๋ต์ ์ ์ฉํ๋ ํจ์
def apply_discount(order_total, customer_type):
discount_strategies = {
'regular': discount_regular,
'premium': discount_premium,
'vip': discount_vip
}
discount_func = discount_strategies.get(customer_type, lambda x: 0)
return discount_func(order_total)
# ์ฌ์ฉ ์์
print(apply_discount(1000, 'regular')) # 50
print(apply_discount(1000, 'vip')) # 150
# ๊ฐ ๋จ๊ณ๋ฅผ ์ฒ๋ฆฌํ๋ ํจ์๋ค
def validate(data):
if not isinstance(data, dict) or 'name' not in data:
return None
return data
def normalize(data):
if data is None:
return None
result = data.copy()
result['name'] = result['name'].strip().lower()
return result
def process(data):
if data is None:
return None
result = data.copy()
result['processed'] = True
return result
# ํ์ดํ๋ผ์ธ ๊ตฌํ
def pipeline(*funcs):
def pipe(data):
result = data
for func in funcs:
result = func(result)
if result is None:
return None
return result
return pipe
# ์ฌ์ฉ ์์
process_data = pipeline(validate, normalize, process)
good_data = {'name': ' John Doe '}
bad_data = {'id': 123}
print(process_data(good_data)) # {'name': 'john doe', 'processed': True}
print(process_data(bad_data)) # None
class UserRepository:
def __init__(self):
self.users = {}
self.next_id = 1
# ๋ช
๋ น ํจ์ (์ํ ๋ณ๊ฒฝ)
def add_user(self, name, email):
user_id = self.next_id
self.users[user_id] = {
'id': user_id,
'name': name,
'email': email
}
self.next_id += 1
return user_id
def update_email(self, user_id, new_email):
if user_id not in self.users:
return False
self.users[user_id]['email'] = new_email
return True
# ์ฟผ๋ฆฌ ํจ์ (์ํ ๋ณ๊ฒฝ ์์)
def get_user(self, user_id):
return self.users.get(user_id)
def find_by_email(self, email):
for user in self.users.values():
if user['email'] == email:
return user
return None
# ์ฌ์ฉ ์์
repo = UserRepository()
user_id = repo.add_user("John Doe", "[email protected]")
print(repo.get_user(user_id))
repo.update_email(user_id, "[email protected]")
print(repo.find_by_email("[email protected]"))