2025. 3. 13. 21:04ㆍPython, Django/Python
원래 사용하던 블로그 - https://yeonnan.hashnode.dev/1?source=more_series_bottom_blogs
파이썬 심화
가상 환경, 코드 컨벤션, 변수 유효 범위, 모듈 및 패턴, 조건문, 함수의 인자와 리턴 타입, 패킹과 언패킹 파이썬 심화 가상환경 (virtual environment) 파이썬에서는 pip를 통해 패키지를 설치하고 관
yeonnan.hashnode.dev
가상환경 (virtual environment)
파이썬에서는 pip를 통해 패키지를 설치하고 관리하는데, 기본적으로 pip로 설치한 패키지들은 파이썬 실행 환경 전체에 영향을 미친다.
그러나 여러 프로젝트를 다룰 때는 버전 충돌 문제가 발생할 수 있는데, 이를 해결하기 위해 파이썬 가상환경을 활용한다.
가상환경은 각 프로젝트마다 독립된 환경을 제공하여 패키지 간의 충돌을 방자히고, 프로젝트 간의 의존성을 관리한다.
이를 통해 각 프로젝트는 자신만의 패키지 버전을 가질 수 있으며, 서로 영향을 주지 않는다.
가상환경 구축
터미널에 python -m venv venv 명령어를 통해 가상환경 구축
명령어를 실행하면 venv라는 이름의 폴더가 생성되고 후에 가상 환경에서 설치하는 패키지들은 이 폴더에 설치된다.
가상환경 활성화
가상환경 활성화를 위해서는 vanv 폴더 내에 있는 activate 파일을 실행시켜야 한다.
source venv/bin/activate
위의 명령어를 통해 가상 환경 활성화가 가능하고, 활성화되면 터미널 좌측에 (venv)가 추가된다.
가상환경 비활성화
deactivate
코드 컨벤션
코드 컨벤션이란 일관성 있고 가독성이 좋은 코드를 작성하기 위한 규칙과 규약을 의미한다.
이는 코드를 작성하는 개발자들이 서로 협업할 때 코드의 일관성을 유지하고 가독성을 높이기 위해 필요하다.
주로 들여쓰기, 변수 및 함수명 작성 규칙, 주석 사용 방법 등이 포함된다.
코드 컨벤션은 언어에 따라 요구하는 내용이 다르기 때문에 내가 개발하는 언어에 맞는 컨벤션 스타일에 맞춰 코드를 작성해야 한다.
파이썬 컨벤션
네이밍 컨벤션으로 변수/함수를 네이밍 할때는 snake표기법, class를 네이밍할 때는 pascal 표기법 사용
- pascal : PythonIsVeryGood - 각 단어를 대문자로 구별
- camel : pythonIsVeryGood - 첫 문자가 소문자로 시작
- snake : python_is_very_good : 각 단어를 _로 구분
클래스, 함수, 변수 등을 네이밍할 때는 이름만 보고 해당 코드가 어떤걸 의미하는지 추측할 수 있어야 한다.
- PI = 3.14 → 상수를 표현할 때는 예외적으로 모든 문자 대문자로 표현
- numbers = [1, 2, 3, 4] → list를 표기할 때는 복수로 표현한다. 혹은 number_list로 표현 for number in numbers
- def add(a, b) : return a + b → 함수를 네이밍할 때는 해당 함수가 어떤 역할을 하는지 표현
변수 유효 범위 (variable scope)
파이썬에서 변수의 유효범위는 변수가 사용할 수 있는 범위를 타나내며, 지역 변수와 전역 변수 두가지가 있다.
지역 변수는 함수 내부에서 선언되며 다른 함수에 영향을 끼치지 않는다.
전역 변수는 함수 밖에서 선언되며 어디서든 접근할 수 있다.
지역 변수 (Local Variable)
def func1():
number = 10 # 함수 내에서 number라는 지역 변수를 선언
def func2():
print(number) # func1에서 생성된 지역 변수는 funt2에서 접근할 수 없다.
func1()
func2()
"""
Traceback (most recent call last):
File "sample.py", line 8, in <module>
func2()
File "sample.py", line 5, in function2
print(number)
NameError: name 'number' is not defined
"""
- 함수 내에서 선언되는 변수로, 해당 함수 내에서만 유효하다.
- 함수가 실행될 때 생성되고, 함수의 실행이 끝나면 사라진다.
- 함수 내부에서만 접근 가능하며, 함수 외부에서는 사용할 수 없다.
전역 변수 (Global Variable):
number = 10 # 함수 밖에서 number라는 전역 변수 생성
def func():
print(number) # 전역 변수는 자유롭게 접근할 수 있다.
func() # 함수를 실행하면 10이 정상적으로 출력된다.
- 함수 외부에서 선언되는 변수로, 스크립트 전체에서 사용할 수 있다.
- 어디서든 접근 가능하지만, 함수 내부에서도 사용 가능하다.
- 전역 변수의 값을 함수 내에서 변경할 때는 global 키워드를 사용하여 명시적으로 선언해야 한다.
변수의 유효범위를 이해하면 함수와 스크립트 전체에서 변수를 사용할 수 있는지 파악할 수 있다.
전역변수 사용시 주의할점
함수 내에서 전역 변수의 값을 바꾸려할 경우
number = 10
def func():
number = 5 # 전역 변수의 값이 바뀌는 것이 아닌, 지역 변수로 다시 선언됩니다.
func()
# 함수 내에서 재할당 된 지역 변수는 전역 변수에 영향을 끼치지 않습니다.
print(number) # 10
전역 변수 사용과 지역 변수 할당을 같이 하는 경우
number = 10
# 전역 변수인 10을 출력하고 지역 변수로 다시 선언하는 코드 작성
def func():
print(number)
number = 5
# 실행시켜 보면 에러가 발생한다.
func()
"""
Traceback (most recent call last):
File "sample.py", line 7, in <module>
func()
File "sample.py", line 4, in func
print(number)
UnboundLocalError: local variable 'number' referenced before assignment
"""
함수 내에서 전역 변수의 값을 바꾸려면
number = 10
def func():
global number # 함수에서 number 변수를 다시 할당할 수 있도록 해줍니다.
number = 5 # global 키워드를 사용했기 때문에 전역 변수의 값이 변경됩니다.
func()
print(number) # 5
모듈 및 패턴
type() / 값의 자료형 확인해보기
특정 모듈을 사용했을 때 그 결과값으로 받아오는 값이 어떤 타입인지 구분하기 어려울때 사용
특정 변수가 어떤 타입의 데이터인지 알수있다.
integer = 10
float_ = 1.23
string = "hello world!!"
list_ = [1, 2, 3]
tuple_ = (1, 2, 3)
set_ = {1, 2, 3}
dictionary = {"key": "value"}
boolean = True
print(type(integer)) # <class 'int'>
print(type(float_)) # <class 'float'>
print(type(string)) # <class 'str'>
print(type(list_)) # <class 'list'>
print(type(tuple_)) # <class 'tuple'>
print(type(set_)) # <class 'set'>
print(type(dictionary)) # <class 'dict'>
print(type(boolean)) # <class 'bool'>
split() / string을 list로 변환하기
# split은 string.split("구분자")로 구성되어 있습니다.
string = "hello/python/world!!"
string_list = string.split("/") # split() 안에 들어간 값을 기준으로 문자를 나눈다.
print(string_list) # ['hello', 'python', 'world!!']
join() / list를 string으로 변환하기
# join은 "사이에 들어갈 문자".join(리스트) 로 구성되어 있습니다.
string_list = ["hello", "python", "world"]
string = "!! ".join(string_list)
print(string) # hello!! python!! world
replace() / 문자열 바꾸기
# replace는 "변경할 문자".replace("변경 전 문자", "변경 후 문자")로 구성되어 있습니다.
before_string = "hello world!!!"
after_string = before_string.replace("!", "~") # !를 ~로 변경
print(after_string) # hello world~~~
pprint() / 코드 예쁘게 출력하기
# pprint는 pretty print의 약자이며, 데이터를 더 예쁘게 출력해 줍니다.
from pprint import pprint
sample_data = {
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{"id": "1001", "type": "Regular"},
{"id": "1002", "type": "Chocolate"},
{"id": "1003", "type": "Blueberry"},
{"id": "1004", "type": "Devil's Food"}
]
},
"topping":
[
{"id": "5001", "type": "None"},
{"id": "5002", "type": "Glazed"},
{"id": "5005", "type": "Sugar"},
{"id": "5007", "type": "Powdered Sugar"},
{"id": "5006", "type": "Chocolate with Sprinkles"},
{"id": "5003", "type": "Chocolate"},
{"id": "5004", "type": "Maple"}
]
}
pprint(sample_data) # print로 출력했을 때와 결과 비교해 보기!!
random / 랜덤한 로직이 필요할 때
# 난수 생성, 임의의 번호 생성 등 랜덤한 동작이 필요할 때 사용
import random
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
random.shuffle(numbers) # numbers를 무작위하게 섞기
print(numbers) # [2, 8, 6, 4, 3, 7, 1, 5]
random_number = random.randint(1, 10) # 1 ~ 10 사이의 무작위 번호 생성
print(random_number) # 4
time / 시간 다루기
import time
start_time = time.time() # 현재 시간 저장
time.sleep(1) # 1초간 대기
end_time = time.time()
# 코드가 종료된 시간 - 코드가 시작된 시간으로 실행 시간 구하기 (단위 : 초)
print(f"코드 실행 시간 : {end_time-start_time:.5f}") # 코드 실행 시간 : 1.00100
datetime / 날짜 다루기
from datetime import datetime, timedelta
# 현재 날짜 및 시간 출력
print(datetime.now()) # 2023-02-22 15:55:32.277095
# datetime의 format code 더 제세한건 여기서 확인 가능합니다.
'''
%y : 두 자리 연도 / 20, 21, 22
%Y : 네 자리 연도 / 2020, 2021, 2022
%m : 두 자리 월 / 01, 02 ... 11 ,12
%d : 두 자리 일 / 01, 02 ... 30, 31
%I : 12시간제 시간 / 01, 02 ... 12
%H : 24시간제의 시간 / 00, 01 ... 23
%M : 두 자리 분 / 00, 01 ... 58, 59
%S : 두 자리 초 / 00, 01 ... 58, 59
'''
# string을 datetime 날짜로 변경하기
string_datetime = "23/12/25 13:20"
datetime_ = datetime.strptime(string_datetime, "%y/%m/%d %H:%M")
print(datetime_) # 2023-12-25 13:20:00
# datetime 날짜를 string으로 변환하기
now = datetime.now()
string_datetime = datetime.strftime(now, "%y/%m/%d %H:%M:%S")
print(string_datetime) # 22/09/04 04:04
# 3일 전 날짜 구하기
three_days_ago = datetime.now() - timedelta(days=3)
print(three_days_ago) # 2023-02-19 16:27:52.526502
조건문
비교문법
비교 연산자들을 사용해 값을 비교하고 결과가 True인지 False인지 판단할 수 있다.
'''== : 값이 일치하는지 비교'''
"a" == "a" # True
"a" == "b" # False
1 == "1" # False, 값은 동일하지만 자료형이 다르기 때문
'''!= : 값이 일치하지 않는지 비교'''
0 != 1 # True
0 != 0 # False
'''>, < : 값이 큰지 작은지 비교'''
5 > 2 # True
1 < 0 # False
1 > 1 # False
'''>=, <= : 값이 크거나 같은지, 작거나 같은지 비교'''
1 >= 1 # True
'''in : 특정 값이 list / tuple / set에 포함되어 있는지 확인'''
4 in [1, 2, 3] # False
1 in (1, 2, 3) # True
# 모든 비교 연산자의 결과는 print()로 확인할 수 있습니다.
print(1 == 1) # True
if, elif, else
if condition: # 조건이 True일 경우
# some code
# not 키워드를 사용할 경우 조건이 False일 때 실행됩니다.
elif not condition: # 조건이 False일 경우
# some code
else: # 위 조건들 중 만족하는게 없을 경우
# some code
if문은 기본적으로 다음에 오는 구문이 true인지 false인지 boolean으로 판단 가능한데, if문을 사용하지 않고도 true인지 false인지 알 수 있다.
user_list = ["철수", "영희"]
# if문은 기본적으로 다음에 오는 구문이 true인지 false인지 boolean으로 판단한다.
if "철수" in user_list:
print("user list에 철수가 있습니다")
else:
print("user list에 철수가 존재하지 않습니다.")
# if문을 사용하지 않고도 true인지 false인지 결괏값을 받을 수 있다.
print("철수" in user_list) # True
and, or
2개 이상의 조건을 복합적으로 사용할 수 있다.
if condition1 and condition2: # 두 조건을 모두 만족할 경우
# some code
elif condition or condition: # 두 조건 중 하나라도 만족할 경우
# some code
else:
# some code
비어있는 string, list 등은 분기문에서 false로 판단한다.
not을 붙이면 뒤에 조건을 만족하지 않을 때 if 문을 통과한다.
# 스트링 안이나 리스트 안에 내용이 담겨 있을 경우에는 분기문을 통과하지 않는다.
# 내용물이 비어있지 않기 때문에 empty_string, empty_list는 true가 되고, not True는 false이기 때문에 분기문을 통과하지 않는다.
empty_string = ""
empty_list = []
# not은 뒤에 있는 조건이 false 일 때 true가 된다.
if not empty_string:
print("string is empty!!")
if not empty_list:
print("list is empty!!")
특정 값이 True인지 False인지는 bool() 함수를 사용해 확인할 수 있다.
print(bool("")) # False
print(bool(0)) # False
print(bool([])) # False
print(bool("sample")) # True
print(bool([1, 2])) # True
print(bool(1)) # True
print(bool(-1)) # 0이 아닌 숫자는 True로 판단
print(bool([""])) # True 빈 리스트 안의 빈 문자열 / 리스트가 false인 조건은 안에 어떠한 요소도 없을 때이다. 현재는 빈 string이라는 요소가 있어서 결과가 true로 나온다.
any() 혹은 all() 함수를 사용해 여러 값들에 대한 조건을 판단할 수 있다.
# all() : 요소들이 모두 True일 경우 True 리턴
if all([True, True, True, False, True]):
print("통과!") # False가 존재하기 때문에 분기문을 통과하지 못함
# any() : 요소들 중 하나라도 True일 경우 True 리턴
if any([False, False, False, True, False]):
print("통과!") # True가 1개 이상 존재하기 때문에 분기문을 통과함
함수의 인자와 리턴 타입
함수들은 비슷해보여도 사용 방법이나 리턴 타입이 다르다.
list를 정렬하기 위해 사용하는 sorted, list.sort()는 사용 방법이 다르다.
# sort
# 변수에 담겨있는 list 자체를 정렬
sample_list = [3, 2, 4, 1, 5]
sample_list.sort() # return data 없이 list 자체를 정렬
print(sample_list) # [1, 2, 3, 4, 5]
# sorted
# 정렬된 list를 return 해주기 때문에 변수에 따로 담아줘야 한다.
sample_list = [3, 2, 4, 1, 5]
sorted_list = sorted(sample_list) # 정렬 된 list를 return
print(sorted_list) # [1, 2, 3, 4, 5]
# 잘못된 방법
sample_list = [3, 2, 4, 1, 5]
sorted_list = sample_list.sort() # .sort()의 return data는 None 입니다.
print(sorted_list) # None
내가 사용하는 코드의 리턴 타입 확인 방법
검색 : 구글에 python 함수명과 같은 형태로 검색해서 해당 기능을 어떻게 사용해야 하는지 확인
docstring 확인 : 함수를 작성할 때 docstring을 활용하면 사용하려는 함수가 어떤 역할을 하는지, 어떤 값을 인자로 받는지, 어떤 값을 리턴해주는지 확인 가능
함수 구현 코드 확인 : 외부 라이브러리를 import해서 사용할 때 권장하는 방법으로 구현부의 코드를 보고 사용 방법을 익히는것이 좋다.
command + 클릭 하면 구현부 코드 확인이 가능하다.
try / exception을 활용한 에러 처리
파이썬에서는 try exception을 사용해 에러가 발생했을 때 처리할 수 있다.
number = "num"
try: # try 구문 안에서 에러가 발생할 경우 except로 넘어감
number = int(number) # "num"을 숫자로 바꾸는 과정에서 에러 발생
except: # 에러가 발생했을 때 처리
print(f"{number}은(는) 숫자가 아닙니다.")
에러 종류에 따른 로직 처리
number = input()
try:
int(number)
10 / number
except ValueError: # int로 변환하는 과정에서 에러가 발생했을 떄
print(f"{number}은(는) 숫자가 아닙니다.")
except ZeroDivisionError: # 0으로 나누면서 에러가 발생했을 때
print("0으로는 나눌수 없습니다.")
except Exception as e: # 위에서 정의하지 않은 에러가 발생했을 때(권장하지 않음)
print(f"예상하지 못한 에러가 발생했습니다. error : {e}")
# except 문법 또한 if / elif와 같이 연달아서 작성할 수 있습니다.
패킹과 언패킹
패킹(packing)과 언패킹(unpacking)은 요소들을 묶어주거나 풀어주는 것을 의미한다.
list, dictionary의 값을 함수에 입력할 때 주로 사용한다.
list에서의 활용
def add(*args):
result = 0
for i in args:
result += i
return result
numbers = [1, 2, 3, 4]
print(add(*numbers))
""" 아래 코드와 동일
print(add(1, 2, 3, 4))
"""
# result output
"""
10
"""
dictionary의 활용
def set_profile(**kwargs):
profile = {}
profile["name"] = kwargs.get("name", "-")
profile["gender"] = kwargs.get("gender", "-")
profile["birthday"] = kwargs.get("birthday", "-")
profile["age"] = kwargs.get("age", "-")
profile["phone"] = kwargs.get("phone", "-")
profile["email"] = kwargs.get("email", "-")
return profile
user_profile = {
"name": "lee",
"gender": "man",
"age": 32,
"birthday": "01/01",
"email": "python@sparta.com",
}
print(set_profile(**user_profile))
""" 아래 코드와 동일
profile = set_profile(
name="lee",
gender="man",
age=32,
birthday="01/01",
email="python@sparta.com",
)
"""
# result print
"""
{
'name': 'lee',
'gender': 'man',
'birthday': '01/01',
'age': 32,
'phone': '-',
'email': 'python@sparta.com'
}
"""
class
파이썬의 클래스는 과자 틀을 만드는 것이고, 과자 틀을 사용해서 찍어낸 쿠키가 인스턴스다.
__init__
class에 __init__ 메서드를 사용할 경우 인스턴스 생성 시 해당 메서드 실행된다.
class CookieFrame():
def __init__(self, name):
print(f"생성 된 과자의 이름은 {name} 입니다!")
self.name = name
cookie1 = CookieFrame("cookie1") # 생성 된 과자의 이름은 cookie1 입니다!
cookie2 = CookieFrame("cookie2") # 생성 된 과자의 이름은 cookie2 입니다!
상속
class 상속이란 클래스를 생성할 때 다른 클래스에 선연된 변수, 메서드 드으이 기능을 가져와 사용할 수 있게 해주는 기능이다.
동일한 코드를 여러 클래스에서 조금씩 수정해 사용하거나 모듈에 내장되어 있는 클래스를 변경할 때 주로 사용된다.
상속 받은 클래스를 기반으로 새로운 클래스 만들기
class Monster():
def __init__(self, hp):
self.hp = hp
def attack(self, damage):
self.hp -= damage
def status_check(self):
print(f"monster's hp : {self.hp}")
class FireMonster(Monster):
def __init__(self, hp):
self.attribute = "fire"
# super()를 사용하면 부모 클래스의 코드를 그대로 사용할 수 있습니다.
# 해당 코드는 self.hp = hp 코드를 실행시키는 것과 동일합니다.
super().__init__(hp)
# 부모 클래스에 존재하는 status_check 메소드를 overriding 합니다.
def status_check(self):
print(f"fire monster's hp : {self.hp}")
class IceMonster(Monster):
def __init__(self, hp):
self.attribute = "ice"
super().__init__(hp)
def status_check(self):
print(f"ice monster's hp : {self.hp}")
fire_monster = FireMonster(hp=100)
# FireMonster 클래스에는 attack 메소드가 없지만
# 부모 클래스에서 상속받았기 때문에 별도의 선언 없이 사용 가능합니다.
fire_monster.attack(20)
fire_monster.status_check()
ice_monster = IceMonster(hp=200)
ice_monster.attack(50)
ice_monster.status_check()
상속 받은 클래스의 특정 코드를 변경해 사용하기
class Calc:
def _print_zero_division_error(self):
print("can't be division by zero")
def plus(self, num1, num2):
...
def minus(self, num1, num2):
...
def divide(self, num1, num2):
if num2 == 0:
self._print_zero_division_error()
return False
...
def multiply(self, num1, num2):
...
calc = Calc()
calc.divide(5, 0)
# result print
"""
can't be division by zero
"""
이 코드는 0으로 나눴을 때 영어로 에러를 출력하는데 영어가 아닌 한글로 출력하고 싶을때는, 상속을 활용하면 코드를 다시 만들거나 모듈 내 코드를 변경하지 않고 원하는 코드로 수정할 수 있다.
class CustomCalc(Calc):
def _print_zero_division_error(self):
print("0으로는 나눌 수 없습니다.")
calc = CustomCalc()
calc.divide(5, 0)
"""
0으로는 나눌 수 없습니다.
"""
class 객체 (object) 다루기
객체
객체와 인스턴스는 동일한 용어로 CookieFrame 클래스를 사용해 생성된 cookie를 “객체” 혹은 “CookieFrame의 인스턴스”라고 표현한다.
객체사용법
list, dict와 같은 자료형 데이터를 생성하고 활용했던 것들이 모두 해당 클래스의 객체를 생성하고 메서드를 활용하는 과정이었다.
sample_list = [1, 2, 3, 4]
sample_dict = {"key": "value"}
print(type(sample_list)) # <class 'list'>
print(type(sample_dict)) # <class 'dict'>
sample_list.sort() # list 클래스의 sort 메소드 사용
datetime 모듈에서 객체 활용
객체에서 사용 가능한 메서드들은 함수의 리턴 타입을 확인하는 방법과 동일하게 검색, docstring, 구현 코드등을 확인하여 찾을 수 있다.
정규표현식 (regex)
regular expression의 약자인 regex라고도 하며 문자열이 특정 패턴과 일치하는지 판단하는 형식 언어
메일이 유효한 이메일인지, 유효한 핸드폰 번호를 입력했는지, 대문자로 시작하고 숫자로 끝나는 패턴의 단어가 몇번 반복되는지 등 다양한 패턴을 지정하고 검증할 수 있다.
정규표현식 예제
유효한 이메일인지 판단하는 최소한의 패턴은 아래와 같습니다.
- 숫자, 알파벳 대/소문자, 일부 특수문자( - _ . )를 조합한 문자로 시작합니다.
- 문자열 중간에는 @가 반드시 1개 포함되어 있어야 합니다.
- @ 이후에는 숫자, 알파벳 대/소문자, 일부 특수문자( - _ . )를 조합한 문자가 들어갑니다.
- 3번 문자 이후에는 .이 한 개 이상 포함되어 있어야 합니다.
- 마지막 . 이후에는 2 ~ 4글자의 숫자, 알파벳 대/소문자, 일부 특수문자( - _ )를 조합한 문자 포함되어 있어야 합니다.
정규표현식 없이 위 조건들을 만족하기 위해서는 아래와 같이 코드를 작성해야한다.
from pprint import pprint
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
number = "0123456789"
special_char = "-_."
def verify_email(email):
# 이메일에 @가 한개 포함되어 있는지 확인
if email.count("@") != 1:
return False
# @를 기준으로 사용자명과 도메인을 분리
username, domain = email.split("@")
# username이 1자 이상인지 확인
if len(username) < 1:
return False
# 도메인에 한개 이상의 .이 포함되어 있는지 확인
if domain.count(".") < 1:
return False
# username에 알파벳, 숫자, 허용된 특수문자 이외의 문자가 포함되어 있는지 확인
if not all([x in alphabet + number + special_char for x in username]):
return False
# domain에 알파벳, 숫자, 허용된 특수문자 이외의 문자가 포함되어 있는지 확인
if not all([x in alphabet + number + special_char for x in domain]):
return False
# 마지막 .을 기준으로 도메인을 분리
_, last_level_domain = domain.rsplit(".", 1)
# 마지막 레벨의 도메인의 길이가 2~4글자인지 확인
if not 2 <= len(last_level_domain) <= 4:
return False
# 모든 검증이 완료되면 True를 리턴
return True
test_case = [
"apple", # False
"sparta@regex", # False
"$parta@regex.com", # False
"sparta@re&ex.com", # False
"sparta@regex.com", # True
"sparta@regex.co.kr", # True
"sparta@regex.c", # False
"sparta@regex.cooom", # False
"@regex.com", # False
]
result = [{x: verify_email(x)} for x in test_case]
pprint(result)
정규표현식을 사용할 경우 코드를 매우 간소화 시킬 수 있다.
from pprint import pprint
import re
# rstring : backslash(\)를 문자 그대로 표현
# ^[\w\.-]+@([\w-]+\.)+[\w-]{2,4}$ : 이메일 검증을 위한 정규표현식 코드
email_regex = re.compile(r"^[\w\.-]+@([\w-]+\.)+[\w-]{2,4}$")
def verify_email(email):
return bool(email_regex.fullmatch(email))
test_case = [
"apple", # False
"sparta@regex", # False
"$parta@regex.com", # False
"sparta@re&ex.com", # False
"spar_-ta@regex.com", # True
"sparta@regex.co.kr", # True
"sparta@regex.c", # False
"sparta@regex.cooom", # False
"@regex.com", # False
]
result = [{x: verify_email(x)} for x in test_case]
pprint(result)
파일과 디렉토리
glob을 활용한 목록 확인
from pprint import pprint
import glob
# ./는 현재 python 파일이 위치한 경로를 의미합니다.
# *은 "모든 문자가 일치한다" 라는 의미를 가지고 있습니다.
# ./venv/*은 venv 폴더 내 모든 파일들을 의미합니다.
path = glob.glob("./venv/*")
pprint(path)
# result output
"""
['./venv\\Include', './venv\\Lib', './venv\\pyvenv.cfg', './venv\\Scripts']
"""
# **은 해당 경로 하위 모든 파일을 의미하며, recursive 플래그와 같이 사용합니다.
# recursive를 True로 설정하면 디렉토리 내부의 파일들을 재귀적으로 탐색합니다.
path = glob.glob("./venv/**", recursive=True)
pprint(path)
# result output
"""
['./venv\\',
'./venv\\Include',
'./venv\\Lib',
'./venv\\Lib\\site-packages',
'./venv\\Lib\\site-packages\\autopep8-2.0.1.dist-info',
...
]
"""
# *.py와 같이 작성 시 특정 확장자를 가진 파일들만 볼 수 있습니다.
# ./venv/**/*.py는 venv 하위 모든 폴더들을 재귀적으로 탐색하며 .py 확장자 파일을 탐색합니다.
path = glob.glob("./venv/**/*.py", recursive=True)
pprint(path)
# result output
"""
['./venv\\Lib\\site-packages\\autopep8.py',
'./venv\\Lib\\site-packages\\pycodestyle.py',
'./venv\\Lib\\site-packages\\pip\\__init__.py',
'./venv\\Lib\\site-packages\\pip\\__main__.py',
'./venv\\Lib\\site-packages\\pip\\__pip-runner__.py',
...
]
"""
open을 활용
# python에서는 파일을 편집하거나 생성할 때, with open 문법을 사용할 수 있습니다.
# "file.txt" : 파이썬에서 사용할 파일을 지정합니다.
# "w" : 파일을 쓰기 모드로 엽니다. 만약 파일이 없다면 새로 생성합니다.
# r, a, 등 다양한 mode가 존재하며, 더 많은 mode의 종류는 여기서 확인할 수 있습니다.
# encoding : 파일의 encoding 형식을 지정합니다.
# case 1. open 함수를 사용해 파일 열기
f = open("file.txt", "w", encoding="utf-8")
f.write("파이썬 파일 쓰기 테스트!\n")
# open 함수를 실행하면 python 스크립트가 끝날때 까지 파일이 열려있게 됩니다.
# 때문에 파일에 대한 작업이 끝나면 close()를 사용해 파일을 닫아줘야 합니다.
f.close()
# open을 with와 같이 사용하면 with 구문이 끝날 때 자동으로 파일이 close 됩니다.
# 때문에 with를 사용할 떄는 별도로 close 해주지 않아도 됩니다.
# a 모드는 기존 내용을 유지한 상태로 추가합니다.
with open("file.txt", "a", encoding="utf-8") as w:
w.write("파이썬 내용 추가 테스트!")
# r 모드는 파일을 읽기 모드로 엽니다.
with open("file.txt", "r", encoding="utf-8") as r:
# readlines는 파일의 모든 내용을 list 자료형으로 한번에 읽어들입니다.
print(r.readlines())
# result output
"""
['파이썬 파일 쓰기 테스트!파이썬 내용 추가 테스트!']
"""
with open("file.txt", "r", encoding="utf-8") as r:
while True:
# readline은 파일을 한 줄 씩 읽어들입니다.
line = r.readline()
# 파일 끝까지 텍스트를 읽어들였다면 반복문을 중지합니다.
if not line:
break
# 텍스트의 줄바꿈 문자 제거
line = line.strip()
print(line)
# result output
"""
파이썬 파일 쓰기 테스트!
파이썬 내용 추가 테스트!
"""
'Python, Django > Python' 카테고리의 다른 글
[python study note] replace, len, sort, sorted, range, map, split, isdigit (0) | 2025.03.13 |
---|---|
[python study note] 클래스, 객체, 인스턴스, 메서드, self (0) | 2025.03.13 |
[python study note] 파이썬 기초 (0) | 2025.03.13 |
[python study note] 모듈 (0) | 2025.03.13 |
[python study note] 가변타입, 불변타입, 절차 지향 프로그래밍 (0) | 2025.03.13 |