11. 파이썬이란 무엇인가 ? 그 이점을 나열하라.
파이썬은, 고급 객체 지향 프로그래밍 언어로, 간결하고 읽기 쉬운 문법과 구조를 가지고 있다.
특히 객체, 모듈, 자동 메모리 관리 기능을 가지고 있으며,
인터프리터 기반의 언어로, 소스코드를 인터프리터가 바이트 코드로 변환하여 PVM에서 실행하게 된다.
즉 크로스 플랫폼 언어로서, 다양한 운영 체제 에서 실행할 수 있는 높은 호환성을 제공한다.
(다만 파일 시스템 경로 처리, 특정 OS 명령 호출등은 운영체제에 따라 차이가 있을 수 있다)
python은 오늘날 데이터 과학, 인공지능, 머신러닝 프로젝트에서 필수적인 도구이며, python이 내장 데이터 구조를 제공해 복잡한 데이터를 효율적으로 처리할 수 있도록 돕기 때문이다. 예를들어 pandas와 numpy 같은 라이브러리를 활용하면 대규모 데이터셋을 쉽고 간결하게 분석할 수 있다.
또한 다양한 모듈과 패키지를 지원하므로, 어플리케이션 개발을 간단하게 만들어준다. 또, pythonic한 코드는 더 적은 양의 코드로 동일한 기능을 구현할 수 있어, 개발 생산성을 크게 향상 시킨다. python의 문법은 매우 직관적이고 쉬워, 다양한 도메인의 팀원과 협업할때, 서로간의 소통을 원활히 할 수 있다.
12. 파이썬은 객체지향언어인가 함수형 언어인가 ?
파이썬은 객체지향 프로그래밍 언어로써, 메소드와 데이터를 사용해 클래스와 객체를 정의하고 사용할 수 있다, 파이썬에서는 모든 것이 객체이며 모든 핵심 원칙을 지원한다. 다만 파이썬은 객체지향적이면서도 다른 패러다임을 자유롭게 혼합할 수 있어 특정 상황에서는 객체지향 원칙을 완전히 따르지 않아도 된다. 파이썬에서는 클래스 없이도 절차적 코딩으로 작업이 가능하다.(함수 작성) 반면 JAVA 같은 언어는 모든 코드를 반드시 클래스 내부에 작성해야한다. 덧붙여 파이썬은 접근제어자를 암묵적으로만 제공하여 객체지향 원칙을 강제하지 않는다.
파이썬은 일급함수, 익명함수, 고차 함수등의 FP 기능을 제공한다.
13. 파이썬의 지역변수와 전역변수는 어떤 규칙에 따라 작동하는가 ?
변수는 데이터를 라벨링하고 저장 하기 위해 사용된다.
파이썬에서 지역변수와 전역 변수의 동작은, 스코프와 관련이 있다.
python 변수의 접근 순서는 LEGB 규칙에 따라 결정된다.
Local (함수 내부 지역 스코프), Enclosing(중첩 함수에서 외부 함수의 스코프), Global(모듈 전체 전역 스코프), Built-in(Python이 제공하는 내장 스코프)
지역 변수는 함수 내부에 선언된 변수로 함수 내부에서 접근 가능하며, 함수 호출이 끝나면 소멸된다.
전역 변수는 함수 외부에서 선언된 변수로 함수 내부에서 참조는 가능하나(읽기 전용) 쓰기를 하려면 함수 내부에서 global 키워드를 사용해야 한다. 만약 함수 내부함수에서(local) 외부함수의 변수(enclosing)에 접근해 쓰기를 수행하려면 nonlocal 키워드를 사용해야 한다.
이는 객체의 가변성에 따라 다르게 작동할 수 있는데,
리스트나 딕셔너리, 집합 등 가변 객체에서는 내용을 수정하더라도 동일한 객체가 유지되므로, 기존 객체의 내용을 수정하는 경우에는 해당 키워드가 불필요하다. 하지만, 재할당 시에는 global이나 nonlocal 키워드가 필요하다. (이미 전역 변수로 인식되기 때문) 반면, 변수나 문자열, 튜플 등의 불변 객체에서는 값 변경 시 새로운 객체가 생성되고, 새로운 객체 생성 시 지역 변수로 처리된다. 그러나 global이나 nonlocal 키워드를 사용할 경우, 값 변경 시 새로운 객체가 기존 변수에 재할당되므로 값 쓰기를 활용할 수 있다.
14. 파이썬에서의 슬라이싱.
파이썬의 슬라이싱은 스트링, 리스트, 튜플과 같은 시퀀스 타입에 대해 적용할 수 있으며, 시퀀스를 더 작은 서브 시퀀스로 분리하는 역할을 한다.
seq[start:stop:step]의 문법을 따르며 start(inclusive), stop(exclusive) 하다.
리스트 같은 뮤터블한 시퀀스에서는 슬라이싱을 사용해 시퀀스의 일부를 바꾸거나 삭제하는 것이 가능하다.
my_list[1:3] = [8, 9] # Modifies [2, 3] to [8, 9]
del my_list[2:4] # Deletes elements at indices 2 and 3
슬라이싱은 간결하고 효율적이며 가독성 있는 코드 작성을 도우며, 시퀀스의 일부를 추출하기위한 수동 이터레이션을 대체해준다.
음의 인덱스는 시퀀스의 끝부터 적용되며, 스탑과 스타트 값 생략시 start = 0, stop = len(sequence) 를 따른다.
슬라이싱은 얕은 복사 개념으로, 객체 내부의 요소는 같은 참조를 공유하나, 복사된 최상위 객체는 원본 객체와 다른 객체가 된다.
deepcopy는 리스트 내부의 모든 요소를 재귀적으로 복사해 완전히 새로운 객체를 생성한다.
얕은 복사는 최상위 레벨에서 독립적인 복사를 수행하며, 내부 객체에 대한 참조를 그대로 유지한다. 이로인해 메모리 사용량을 줄일 수 있어 대규모 데이터 구조를 다룰떄 효율적이다. 특히 내부객체를 수정하지 않거나 읽기 전용으로 사용하는 경우 유용하다.
예를들어 append나 pop같은 메서드는 최상위 객체에만 영향을 주므로 원본과 복사본이 서로 독립적으로 동작한다.
하지만 리스트 내부에 가변 객체가 포함된 경우ㅡ 얕은 복사에서는 원본과 복사본이 내부 참조를 공유하기 떄문에, 복사본에서 내부 객체를 수정하면 원본에도 영향을 미친다.
이와달리 깊은 복사는 최상위 객체 뿐 아니라 내부 객체까지 재귀적으로 복사하여, 원본과 복사본을 완전히 독립시킨다. 이로인해 복사본에서 내부객체를 수정해도 원본에 영향을 주지 않는다. 즉 깊은 복사는 복잡한 중첩 데이터 구조를 다룰떄 매우 유용하다.
15. 파이썬에서의 네임스페이스란 무엇인가 ?
네임스페이스는 파이썬에서 스코프 별로 변수명과 함수등 객체간의 값을 딕셔너리로 관리하는 체계이다.
LEGB 스코프 체계에 따라 관리되며 객체의 이름은 키가되고 값은 실제 객체를 참조하게 된다.
x = "global variable" # 전역 네임스페이스
def outer_function():
x = "enclosing variable" # Enclosing 네임스페이스
def inner_function():
x = "local variable" # Local 네임스페이스
print("Local Namespace:", locals()) # 지역 네임스페이스
print("Enclosing Namespace:", outer_function.__code__.co_varnames) # Enclosing 변수 확인
inner_function()
print("Global Namespace:", globals()) # 전역 네임스페이스
outer_function()
print("Built-in Namespace:", dir(__builtins__), print(vars(__builtins__)) ) # 빌트인 네임스페이스
Global namespace before outer call: {'x': 'global', 'outer': <function outer at 0x...>}
Inner locals: {'x': 'local'}
Outer value from inner: local
Outer locals: {'x': 'enclosing'}
Global namespace after outer call: {'x': 'global', 'outer': <function outer at 0x...>}
예를들어 빌트인 네임 스페이스는 기본적으로 파이썬이 제공하는 내장 함수, 내장 예외, 기타 객체들이 포함되며, 프로그램 실행시 기본적으로 로드되어, 모든 파이썬 코드에서 자동으로 접근 가능하다.
16. 파이썬에서 pass란 무엇인가?
pass는 미래 코드 작성을 위한 플레이스 홀더 역할을 한다. 현재 작동이 필요하지 않은 상태에서 유효한 코드 블록의 역할을 하며, 그냥 아무것도 하지 않는, 작동을 한다. 파이썬은 반복문, 클래스 정의, 조건문, 함수 정의 등에서 빈 코드블록을 허락하지 않는다.
만약 구현할 로직을 결정하지 못했고, 함수를 정의하는 단계라면, 신택스 에러를 피하기 위해 pass 를 사용할 수 있다. 파이썬 인터프리터에서, 주석과는 다르게, pass는 무시되지 않으며, novalue 를 반환한다.
In Python, the pass statement serves as a placeholder for future code. It allows you to write syntactically valid code blocks where no operation is currently needed. When the pass statement is executed, it performs no action, essentially acting as a 'do nothing' operation.
It is particularly useful in scenarios where Python does not permit empty code blocks, such as within loops, class definitions, conditional statements, or function definitions. For example, if you're defining a function but haven't yet decided what logic to implement, you can use pass to avoid syntax errors.
Unlike comments, which are completely ignored by the Python interpreter, the pass statement is not ignored—it is executed but returns no value. This makes pass a valid statement in Python that plays a crucial role in maintaining the structure of your code during development.
17. 파이썬에서 유닛테스트란 무엇인가 ?
파이썬에서의 유닛테스트는, 빌트인 테스트 프레임워크로, 정렬되고 자동화된 형태의 테스트케이스 작성을 가능하게 한다.
xUnit 스타일을 따르며,
xUnit 테스트는 소프트웨어 테스트를 체계 적으로 수행하기 위한 단위 테스트 프레임워크의 일반적인 아키텍쳐 스타일을 말한다. x는 다양한 언어 별로 구현된 테스트 프레임 워크의 이름을 일반화 한것으로, python의 unittest, java의 jtest, c#의 Nunit등이 있다.
x유닛 테스트 아키텍쳐는 다음과 같은 형태를 따른다.
함수, 메서드, 클래스 단위의 특정 기능이나 컴포넌트를 독립적으로 검증하기 위해 설계된 테스트.
test case, test suite, test runnerm assertion 의
테스트 케이스 작성해, 여러게의 케이스를 스위트로 묶어 관리. 테스트를 러너로 실행. 결과 보고 등의 기본 구조를 따른다. CI/CD 파이프라인에서 테스트 자동화를 쉽게 구현하였다. regression의 감지와 셋업과 티어다운을 활용, 테스트 환경과 결과를 셋업하고 클리닝업한다.
pytest도 x유닛 테스트 아키텍쳐를 따르며 보일러 플레이트가 조금 더 적다.
unittest in python is a built-in testing framework that enables the creation of structured and automated test cases. It floolows the xUnit style, which is a general architecture for unit testing frame works implemented in various programming languages, such as Python's unit test, java's JUnit and C#'s NUnits
xUnit architecture includes key components like
Test Case A single unit of testing to verify specific functionality.
Test Suite A collection of test cases grouped together.
Test Runner Executes the tests and reports the results.
Assertions Verifies whether the test outcomes match expectations.
Unittest makes it easy to detect regressions when changes are made to the code. it supports setup and teardown methods, allowing you to prepare the environment before test and clean up afterwrad, ensuring the test are independent and repeatable.
Unittest is widely used in CI/CD pipelines where automated testing ensures consistent code quality and stability. While pytest also follows the xUnit architecture, it reduces boilerplate code, making it more concise and flexible for larger projects.
import unittest
# Function to test
def add(a, b):
return a + b
# Test cases
class TestMathOperations(unittest.TestCase):
def setUp(self):
print("Setting up test environment...")
def tearDown(self):
print("Cleaning up after test...")
def test_add(self):
self.assertEqual(add(2, 3), 5)
self.assertNotEqual(add(2, 3), 6)
def test_add_negative(self):
self.assertEqual(add(-1, -1), -2)
# Test Suite
def suite():
suite = unittest.TestSuite()
suite.addTest(TestMathOperations('test_add'))
suite.addTest(TestMathOperations('test_add_negative'))
return suite
if __name__ == '__main__':
# Run the test suite
runner = unittest.TextTestRunner()
runner.run(suite())
import pytest
# Function to test
def add(a, b):
return a + b
# Test cases
def test_add():
assert add(2, 3) == 5
assert add(2, 3) != 6
def test_add_negative():
assert add(-1, -1) == -2
# Fixtures (Setup and Teardown)
@pytest.fixture
def sample_data():
print("Setting up test environment...")
yield [1, 2, 3]
print("Cleaning up after test...")
def test_sample_data_sum(sample_data):
assert sum(sample_data) == 6
18. 파이썬에서 네거티브 인덱스란 무엇인가 ?
파이썬의 네거티브 인덱싱은, 리스트나 어레이의 끝에서 엘리먼트에 접근할 수 있게 해준다. 대부분의 프로그래밍 언어들이 0부터 시작하는 양의 인덱스를 사용하지만, 파이썬만 둘다 지원한다.
포지티브 인덱싱에서 첫 요소는 인덱스 0 부터 시작한다. 네거티브 인덱싱에서 첫 요소는 마지막부터 -1로 시작한다.
이 기능은 정확한 길이를 모를때 끝부분 리스트부터 요소를 접근하는데 매우 유용하다. 이는 코드를 더 간결하고 가독성있게 만들어준다.
Negative indexing in Python allows you to access elements from the end of a list or array.
While most programming languages use positive indexing, starting from -0 for the first element, Python uniquely supports both positive and negative indexing.
In positive indexing the first element is at index 0 in negative indexing the last element of the array is accessed with -1. and second to last with -2 and so on
This feature is. especially useful for accessing elements at the end of a list without knowing its exact length. For instance if you want to retrieve the last few elements of a dynamically sized list, negative indexing makes it more concise and readable.
19. 파이썬에서 ODBC 모듈이란 무엇인가.
ODBC 는 DBMS의 연결을 지원하는 표준 API이다. 시초는 C언어였지만 ODBC 드라이버와 ODBC 모듈을 통해 하나의 표준 인터페이스로 모든 DBMS에 접근 가능하다.
psycopg2같은 파이썬 전용 postgres 전용 드라이버를 사용한다면 ODBC와 같은 추가 계층 필요가 없어 좀더 효율 적일 수도 있겠다.
하지만 DBMS 종속적이며 여러 이비를 참조한다면 부적합할 수 있다.
파이썬의 ODBC인터페이스, ODBC드라이버 제공은 거의 모든 데이터베이스에서 이루어진다.
보통 파이썬은 ODBC모듈로 pyodbc(크로스 플랫폼), MxODBC(상용 모듈), PythonWin(윈도우 전용) 등을 사용한다.
ODBC 모듈은 데이터베이스 독립적 어플리 케이션을 만들 수 있게 해주고, 디비 솔루션에 유연성과 경쟁력을 부여한다.
덧붙여 커서와 디비 객체에 대해 설명해보자면 디비 객체는 데이터베이스와의 네트워크 연결을 관리하는 객체, 커서는 디비 객체 안에서 여러개 생성되어 쿼리 실행과 결과를 처리하기 위한 객체이다.추상화된 객체로 좀이를 통해 병렬처리, 배치작업, 대량 데이터 처리등의 기능을 제공한다. Python DB-API PEP249표준에 따르면 SQL 쿼리를 실행시 반드시 커서 객체를 사용하도록 규정되어 있다.(유연성, 확장성, 책임의 분리)
ODBC is a standard API that supports connections to DBMS. initially developed for the Cprogramming languagem ODBC allows access to multiple DBMS through a single standard interface by using ODBC drivers and ODBC modules.
Using Python-specific database driver like psycopg2(dedicated to PostgreSQL) eliminates the need for the additional abstraction layer provided by ODBC, potentially making it more efficient. Howerverm such drivers are DBMS-specific and may not be suitable for applications requiring access to multiple databases.
Python's ODBC interface and the provision of ODBC drivers are available for nearly all databases. Common ODBC modules in Python include
1.pyodbc A cross-platform ODBC module.
2.MxODBC A commercial module optimized for stability and performance.
3.PythonWin ODBC: An ODBC Module designed specifically for Windows environments
ODBC modules enable the creation of database-agnostic applications, providing flexibility and competitiveness in database solutions.
In Python, a DB Object manages the network connection to the database, acting as a session manager while also being responsible for creating cursors. A Cursor is created within a database object and is used to execute queries and process results. Multiple cursors can be created within a single database objectm enabling tasks such as parallel processingm batch operations, and handling large datasets. by abstracting cursors provide an efficient and scalable way to interact with databases. Importantlym according to Python DB-API(PEP 249) all SQL queries must be executed through cursor objects. This design ensures flexibllitym scalability, and a clear separation of responsibilities between database objects and cursors.
20. 파이썬 스크립트에서 이메일 보내는 법
파이썬에서 이메일 보내는 것은 빌트인 smtplib 라이브러리를 사용할 수 있다, 이것은 SMTP 클라이언트 세션 오브젝트를 활용해 메시지를 보낼 수 있다.
메시지를 보내는 단계는 다음과 같다.
1. 연결 생성
smtp_ssl()이나, starttls()같은 메서드를 사용해, 연결한다. (각각 ssl, tls 방식 보안화 활용)
2. 이메일 크레덴셜을 활용해 authentication. smtp 클라이언트 세션 객체를 생성한다.
3. 이메일을 구성한다. (플레인 텍스트나, html같은 리치텍스트 방식, 첨부 파일등),
4. csv파일을 읽어, 수신인등의 정보를 가져와 이메일을 개별화해 전송한다.
5. yagmail은 보일러 플레이트 코드를 줄이고 지메일 계정으로 메일을 전송하기 편한 모듈이다.
import csv
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
# Email credentials
sender_email = "your_email@gmail.com"
password = "your_password"
# CSV 파일에서 수신자 정보를 읽어 이메일 발송
with open("contacts.csv", newline="") as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
receiver_email = row["email"]
recipient_name = row["name"]
# 이메일 구성
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = "Personalized Email with Attachment"
body = f"Hello {recipient_name},\nThis is a personalized email with an attachment!"
message.attach(MIMEText(body, "plain"))
# 첨부 파일 추가
filename = "test_file.txt" # 첨부할 파일 이름
try:
with open(filename, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part) # 파일을 Base64로 인코딩
part.add_header(
"Content-Disposition",
f"attachment; filename={filename}",
)
message.attach(part)
except FileNotFoundError:
print(f"Attachment file {filename} not found!")
continue # 첨부 파일 없으면 해당 수신자 건너뛰기
# 이메일 전송
try:
with smtplib.SMTP("smtp.gmail.com", 587) as server:
server.starttls() # TLS 보안 연결
server.login(sender_email, password)
server.send_message(message)
print(f"Email sent to {recipient_name} at {receiver_email}")
except Exception as e:
print(f"Error occurred while sending to {recipient_name}: {e}")
sending emails in Python can be achieved using the built-in smtplib library, which allows the creation of an SMTP client session object to send messages.
First, a connection is established using methods like SMTP_SSL() or .starttls(), which utilize SSL or TLS enscryption for secure communication with the SMTP server. After establishing the connection, authentication is performed by logging in with email credentials to create an authenticated client session.
The email is then composed, either as plain text or HTML for rich text formatting, with optional attachments added using the MIMEBase module. Recipient information, such as names and email addresses, can be read from a CSV file to dynamically. personalize and send emails. Alternatively, the Yagmail library simplifies the process by reducing boilerplate code and providing an easy way to send emails via Gmail accounts, making it a convenient option for streamlined email automation.
'python' 카테고리의 다른 글
python - interview questions (Turing) Q1 ~ Q10 (1) | 2024.12.19 |
---|
댓글