배꼽파지 않도록 잘 개발해요

[코드잇] Python 환경 - 파이썬 모듈과 패키지 본문

코드잇 Codeit/Python / ML / DL

[코드잇] Python 환경 - 파이썬 모듈과 패키지

꼽파 2023. 11. 4. 17:43


  • 1. 모듈

  • 2. 패키지

  • 3. 외부 패키지 사용하기

  • 1. 모듈

    모듈

    여러 기능을 모아둔 파이썬 파일

    프로그램을 짤 때에는 코드를 파일 단위로 나눠주는 게 좋음.
    ex. items.py, transactions.py
    파일 하나 = 모듈(Module)

    코드를 한 파일 안에 넣으면 코드를 모듈화시키면
    - 어느 부분이 어떤 역할을 하는지
    - 기능을 수정하고 싶으면 어떤 부분을 바꿔야 하는지
    알기 힘들다.
    - 한 파일에서 구현하고자 하는 게 더 명확해짐.
    - 코드를 재사용할 수 있음.

    특정 기능이 여러 프로그램에서 필요한 경우 그 기능을 구현하는 모듈을 가져와서 쓰면 됨.

     

    import <module>
    from <module> import <member(s)>
    from <module> import *
    from shapes2d import Square as Sq
    
    '''
    shapes2d.py
    class Square
    '''
    
    square = Sq(3)  # Square(Sq)의 인스턴스 생성
    print(square.area())  # Square의 area메소드 사용

     

    area.py

    여러 도형의 면적을 구해주는 함수를 모아놓은 모듈

    PI = 3.14
    
    def circle(radius):
    	"""원의 넓이를 구하는 함수"""
        return PI * radius * radius
    
    def square(length):
    	"""정사각형 넓이를 구하는 함수"""
        return length * length

     

    run.py

    import area
    # area 모듈 불러오기
    # area의 모든 함수와 변수 사용 가능함.
    
    # area모듈의 circle 함수
    print(area.circle(2))  # 12.56
    
    # area모듈의 square 함수
    print(area.square(3))  # 9
    
    # area모듈의 변수 PI
    print(area.PI)  # 3.14
    # area 모듈의 circle 함수만 필요함
    from area import circle, square
    
    print(circle(2))  # 12.56
    print(square(4))  # 16
    # area 모듈을 ar이라는 이름으로 사용
    # alias는 모듈의 실제 이름과 유사한 걸로 사용하면 좋음
    
    import area as ar
    from area import square as sq
    
    print(ar.circle(3))  # 12.56
    print(ar.sq(3))  # 오류
    print(sq(6))  # 36
    from area import *
    
    # 어떤 모듈의 어떤 함수를 불러왔는지 알 수 없음
    # --> 사용 지양
    print(square(3))  # 9
    print(circle(2))  # 12.56
    print(PI)  # 3.14

    이미지를 비트맵 형식으로 표현

    def display(img):
        height, width = len(img), len(img[0])
        for i in range(height):
            for j in range(width):
                print(img[i][j], end=' ')
            print()
            
    img2=[
        [10001],
        [00011],
        [00101],
        [01001],
        [11111]]
        
    print(display(img2))
    ERROR!
    File "<string>", line 10
        [00011],
         ^^^
    SyntaxError: leading zeros in decimal integer literals are not permitted; 
    use an 0o prefix for octal integers

    10진수에서 저렇게 쓰는 건 허용되지 않음.

    그래서 str로 변환해줘서 리스트로 넣어줌.

     

    리스트 슬라이싱 목적

    # 이미지를 파일에서 읽어오는 함수
    def read_image(filepath):
        img = []
        with open(filepath, 'r') as f:
            data = f.readlines()  # 파일의 각 줄마다 읽어와 리스트로 반환함
    
        for row in data:  # row의 끝에는 '\n'이 있음.
            row = row[:-1]  # -1은 마지막 원소를 의미함. "마지막 직전까지" 슬라이싱 -> '\n' 삭제
            img.append([int(bit) for bit in row])  # 리스트의 원소를 하나씩 정수로 변환
        return img  # img의 숫자는 현재 정수임
    # 이미지 색상 반전
    def invert(img):
        # img 이미지 크기
        height, width = len(img), len(img[0])
        new_img = []
        for i in range(len(img)):
            new_row = []
            for bit in img[i]:
                new_row.append(invert_bit(bit))
            new_img.append(new_row)
        return new_img
    def invert(img):
        # img 이미지 크기
        height, width = len(img), len(img[0])
        new_img = []
        for i in range(len(img)):
            for bit in img[i]:
                new_img.append([])
                new_img[i].append(invert_bit(bit))
        return new_img

    네임스페이스

     

    dunder (Double UNDERscore)(던더) : 특수변수, 파이썬이 내부적으로 관리하는 변수들

    ex. __file__ : 던더 파일

    import area
    
    print(area)
    """
    <module 'area'
    from 'C:\\Users\\airyt\\PycharmProjects\\pythonProject1\\modules\\area.py'>
    """
    
    print(dir(area))
    """
    ['PI', '__builtins__', '__cached__', '__doc__', '__file__', 
    '__loader__', '__name__', '__package__', '__spec__', 'circle', 'square']
    """
    
    print(dir())
    '''
    ['__annotations__', '__builtins__', '__cached__', '__doc__', 
     '__file__', '__loader__', '__name__', '__package__', '__spec__', 'area']
    모듈을 임포트하면 이 파일에서는 모듈의 이름만 정의되고
    모듈 안에 있는 함수나 변수의 이름들은 정의되지 않음.
    PI, Squre, CIrcle은 안 나옴.
    '''

     

    모듈을 임포트하면 이 파일에서는 모듈의 이름만 정의되고,
    모듈 안에 있는 함수나 변수의 이름들은 정의되지 않음.

    # alias 사용
    import area as ar
    
    print(dir())
    '''
    ['__annotations__', '__builtins__', '__cached__', 
    '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'ar']
    --> area 대신 'ar'로 나오는 걸 확인할 수 있음.
    '''
    # area 모듈의 함수 circle, square 직접 가져오기
    from area import circle, square
    
    print(dir())
    '''
    ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', 
    '__loader__', '__name__', '__package__', '__spec__', 'circle', 'square']
    --> 함수를 직접 임포트 했더니 area는 없고 circle과 square만 나옴.
    '''

     

    네임스페이스 : 파일에서 정의된 모든 이름들

    from area import circle, square
    
    def square(length):
        """정사각형 둘레의 길이"""
        return 4 * length
    
    print(dir())
    '''
    ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', 
    '__loader__', '__name__', '__package__', '__spec__', 'circle', 'square']
    '''
    
    print(square(3))
    # 12
    # 현재 run.py 모듈 안에 있는 square 함수(둘레)가 호출됨.

    여기서 square(3)의 값이 12로 나온 걸 보면 해당 파일 안에 있는 square 함수가 호출된 것을 알 수 있음.
    파이썬에서는 똑같은 이름으로 여러 함수가 정의되었을 떄 가장 나중에 정의된 함수를 씀.

     

    이름이 중복되면 어떤 함수를 참조하는지 알기 힘듦.
    한 네임스페이스 안에는 같은 이름이 중복되지 않는 것이 좋음.

     

     

    중복되지 않게 하는 방법

     

    1. 해당 함수를 호출할 때 이름을 바꿔줌.

    from area import circle, square as sq

    from area import circle, square as sq
    
    def square(length):
        """정사각형 둘레의 길이"""
        return 4 * length
    
    print(dir())
    '''
    ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', 
    '__loader__', '__name__', '__package__', '__spec__', 'circle', 'sq', 'square']
    '''
    print(square(3))
    # 12
    # 현재 run.py 모듈 안에 있는 square 함수(둘레)가 호출됨.
    
    print(sq(3))
    # 9
    # area 모듈 안에 있는 square 함수(면적)가 호출됨.

     

    2. 모듈 그대로 import 함.

    import area
    area.함수

    import area
    
    def square(length):
        return 4 * length
    
    print(dir())  # ['__annotations__', '__builtins__', '__cached__', '__doc__', 
    '__file__', '__loader__', '__name__', '__package__', '__spec__', 'area', 'square']
    print(square(3))  # 12
    print(area.square(3))  # 9

     

    from area import *
    - 모듈에서 정의된 모든 이름들을 다 정의함.
    - 같은 이름이 중복될 확률이 높아져서 권장되지 않음.

     

    예시

    ### main.py
    
    def zoo():
        print('zoo() from main')
       
    from mod import zoo
    
    zoo()
    ### mod.py
    
    def zoo():
        print('zoo() from mod')
    
    '''
    main.py 실행결과
    zoo() from mod
    '''

    main에서 from mod import zoo로 mod의 zoo함수를 정의함.

    가장 나중에 정의된 함수가 호출됨.

     

    ### main.py
    
    def zoo():
        print('zoo() from main')
       
    import mod
    
    zoo()
    ### mod.py
    
    def zoo():
        print('zoo() from mod')
    
    '''
    main.py 실행결과
    zoo() from main
    '''

    main에서 import mod만 한 경우

    main에 있는 zoo가 실행됨.


    스탠다드 라이브러리

    • int, float, string 같은 자료형
    • print, dir 같은 내장함수
    • 유용한 기능을 제공하는 모듈들(스탠다드 모듈)

    import math
    
    a = math.log10(2)
    b = math.cos(10)
    
    from math import log10, cos
    
    c = log10(2)
    d = cos(10)
    
    print(a)  # 0.3010299956639812
    print(b)  # -0.8390715290764524
    print(c)  # 0.3010299956639812
    print(d)  # -0.8390715290764524

    https://docs.python.org/ko/3/library/

     

    The Python Standard Library

    While The Python Language Reference describes the exact syntax and semantics of the Python language, this library reference manual describes the standard library that is distributed with Python. It...

    docs.python.org

     

    math

    기본적인 수학 모듈로 여러가지 수학 함수를 제공함.

    import math
    
    # 제곱근 계산
    print(math.sqrt(25))  # 5.0
    
    # 로그 계산
    print(math.log(100, 10))  # 2.0
    
    # 삼각함수 계산
    print(math.sin(math.radians(30)))  # 0.499
    
    # 파이값
    print(math.pi)  # 3.141592

     

    random

    무작위로 수 생성

    import random
    
    # 무작위 정수 생성
    random_int = random.randint(1, 20)  # 1에서 10 사이의 무작위 정수 생성
    print(random_int)
    
    # 무작위 실수 생성
    random_float = random.random()
    print(random_float)
    
    # 무작위 소수 생성
    random_uniform = random.uniform(0, 10)
    print(random_uniform)  # 9.01126192258205
    
    # 리스트 내의 요소 무작위로 섞기
    my_list = [1, 2, 3, 4, 5]
    random.shuffle(my_list)
    print(my_list)
    
    # 무작위 선택
    random_choice = random.choice(["apple", "banana", "cherry"])
    print(random_choice)
    
    # 시드 설정
    random.seed(42)
    # 난수 생성 시 알고리즘의 설정값

     

    datetime

    날짜와 시간 관련

    from datetime import datetime
    # import datetime이라고 하면 datetime.datetime이라고 써야됨.
    
    # 현재 시간과 날짜
    today = datetime.now()
    print(today)  # 2023-09-27 07:55:29.456953
    
    # 특정 날짜 생성
    specific_date = datetime(1999, 9, 19)
    print(specific_date)  # 1999-09-19 00:00:00
    
    # 시간 차이 계산
    time_difference = datetime.now() - datetime(1999, 9, 19)
    print(time_difference)  # 8774 days, 7:58:00.362053
    
    # 날짜 포맷 지정
    formatted_date = today.strftime("%Y-%m-%d %H:%M:%S")
    print(formatted_date)  # 2023-09-27 08:00:14
    
    # 날짜 계산
    new_date = today + datetime.timedelta(days=7)
    print(new_date)  # 2023-09-27 08:01:26

     

    os

    Operating System, 운영체제

    운영체제를 조작하거나 운영체제에 대한 정보 가져오기

    import os
    
    # 현재 어떤 계정으로 로그인 되어 있는지 확인
    print(os.getlogin())  # airyt
    
    # 현재 파일의 디렉토리 확인
    print(os.getcwd())  # C:\Users\airyt\PycharmProjects\pythonProject1\modules
    current_directory = os.getcwd()
    
    # 현재 프로세스 ID 확인
    print(os.getpid())  # 14796
    
    # 디렉토리 생성
    os.mkdir('new_directory')
    # 현재 디렉토리 내에 'new_directory'가 생김
    # 이미 동일한 이름의 디렉토리가 있으면 에러뜸.
    
    # 파일 목록 가져오기
    file_list = os.listdir(current_directory)
    print(file_list)  # ['area.py', 'new_directory', 'run.py', '__pycache__']
    
    # 파일 이름 변경
    os.rename('old_file.txt', 'new_file.txt')  
    # 'old_file.txt'를 'new_file.txt'로 이름 변경

     

    os.path

    import os
    
    file_exists = os.path.exists('file.txt')
    print(file_exists)
    # false
    
    files = ['title.txt', 'area.py', 'run.py']
    file_exists1 = [os.path.exists(file) for file in files]
    print(file_exists1)
    '''
    [False, True, True]
    exist(file)로 file의 경로를 직접 받음.
    '''
    
    files = ['title.txt', 'area.py', 'run.py']
    file_exists2 = [os.path.exists for file in files]
    print(file_exists2)
    '''
    [<function exists at 0x000002155B6D2C20>, <function exists at 0x000002155B6D2C20>, 
    <function exists at 0x000002155B6D2C20>]
    매개변수가 없어서 함수 객체를 참조함.
    '''

    import os
    
    r'''
    ◆ 프로젝트 디렉토리
    C:\Users\airyt\PycharmProjects\pythonProject1\OpenAPI_Image\button.py
    
    ◆ 현재 파일 디렉토리
    C:\Users\airyt\PycharmProjects\pythonProject1\modules\run.py
    '''
    
    # 주어진 경로를 절대 경로로
    print(os.path.abspath('..'))
    # C:\Users\airyt\PycharmProjects\pythonProject1
    
    # 주어진 경로를 현재 디렉토리를 기준으로 한 상대경로로
    print(os.path.relpath(r'C:\Users\airyt\PycharmProjects\pythonProject1'))
    # ..
    
    # 주어진 경로들을 병합
    print(os.path.join(r'C:\Users\airyt\PycharmProjects\pythonProject1','standard_modules'))
    # C:\Users\airyt\PycharmProjects\pythonProject1\standard_modules

     

    re

    Regular Expression (RegEx), 정규표현식

    import re
    
    # 알파벳으로 구성된 단어들만 매칭
    pattern = re.compile('^[A-Za-z]+$')
    '''
    ^ : 문자열의 시작
    [A-Za-z] : 대문자 A부터 Z까지 또는 소문자 a부터 z까지의 알파벳 중 하나
    + : 앞의 패턴이 하나 이상 나오는 것을 의미
    $ : 문자열의 끝
    '''
    print(pattern.match('I'))  # <re.Match object; span=(0, 1), match='I'>
    print(pattern.match('express999'))  # None
    print(pattern.match('Iwantogohome'))  # <re.Match object; span=(0, 12), match='Iwantogohome'>
    
    
    # 숫자가 포함된 단어들만 매칭
    pattern = re.compile('.*\d+')
    '''
    .* : 0개 이상의 어떤 문자든지 나타날 수 있음.
    \d : 하나의 숫자
    + : 앞의 패턴이 하나 이상 나오는 것을 의미함.
    '''
    print(pattern.match('I'))  # None
    print(pattern.match('10041004'))  # <re.Match object; span=(0, 8), match='10041004'>
    print(pattern.match('python3'))  # <re.Match object; span=(0, 7), match='python3'>
    
    
    # 패턴 매칭
    pattern = r'\d+'  # 숫자
    matches = re.findall(pattern, '10 apples and 20 oranges')  # 문자열에서 숫자 찾아서 리스트로 반환
    print(matches)  # ['10', '20']
    
    # 패턴 대체
    new_string = re.sub(pattern, '???', '10 apples and 20 oranges')  # 숫자를 'X'로 대체
    print(new_string)  # ??? apples and ??? oranges
    
    # 패턴 매칭(그룹)
    '''
    (\d{2}) : 두 자리 숫자
    - \d는 숫자를 의미함
    - {2}는 바로 앞에 나온 패턴이 정확히 2번 반복되어야 함을 의미
    (\d{4}): 네 자리 숫자
    '''
    pattern_with_group = r'(\d{2})-(\d{2})-(\d{4})'  # 날짜 패턴
    matches_with_group = re.match(pattern_with_group, '27-09-2023')  # 그룹으로 나누어 매칭
    print(matches_with_group)
    # <re.Match object; span=(0, 10), match='27-09-2023'>
    
    # 패턴 검색
    search_result = re.search(pattern, 'The price is $100')  # 패턴에 매치되는 부분을 검색
    print(search_result)  # <re.Match object; span=(14, 17), match='100'>
    
    # 패턴 컴파일
    compiled_pattern = re.compile(r'[A-Z]+')  # 대문자
    matches = compiled_pattern.findall('Hello World')
    print(matches)  # ['H', 'W']

     

    pickle

    파이썬 객체를 byte 형식으로 바꿔서 파일에 저장할 수 있고, 저장된 객체를 읽어올 수 있음.

    import pickle
    '''
    # wb = write binary mode
    # rb = read binary mode
    '''
    
    # 객체 저장
    data = {'name': 'John', 'age':30, 'city':'New York'}
    with open('data.pkl', 'wb') as file:
        pickle.dump(data, file)
    
    # 객체 불러오기
    with open('data.pkl', 'rb') as file:
        loaded_data = pickle.load(file)
        print(loaded_data)
        # {'name': 'John', 'age': 30, 'city': 'New York'}

     

    jason

    JSON 형식에 맞는 데이터 (기본 데이터 타입들, 리스트, 딕셔너리)만 바꿀 수 있음.

    import json
    
    # 객체를 JSON 문자열로 변환
    data = {'name': 'John', 'age': 30, 'city': 'New York'}
    json_string = json.dumps(data)
    
    # JSON 문자열을 객체로 변환
    json_string = '{"name": "John", "age": 30, "city": "New York"}'
    loaded_data = json.loads(json_string)
    
    # JSON 파일로 저장
    with open('data.json', 'w') as file:
        json.dump(data, file)
    
    # JSON 파일 불러오기
    with open('data.json', 'r') as file:
        loaded_data = json.load(file)
        print(loaded_data)
        # {'name': 'John', 'age': 30, 'city': 'New York'}

     

    copy

    얕은 복사 깊은 복사
    copy.copy() 함수 이용 copy.deepcopy() 함수 이용
    원본 객체와 얕은 복사본 객체가 같은 요소를 공유함. 원본 객체와 깊은 복사본 객체는 완전히 독립적임.
    import copy
    
    # 얕은 복사
    original_list = [1, 2, [3, 4]]
    shallow_copy = copy.copy(original_list)
    
    print(original_list)  # [1, 2, [3, 4]]
    print(shallow_copy)  # [1, 2, [3, 4]]
    
    original_list[2][0] = 100
    print(original_list)  # [1, 2, [100, 4]]
    print(shallow_copy)  # [1, 2, [100, 4]]
    import copy
    
    # 깊은 복사
    original_list = [1, 2, [3, 4]]
    deep_copy = copy.deepcopy(original_list)
    
    print(original_list)  # [1, 2, [3, 4]]
    print(deep_copy)      # [1, 2, [3, 4]]
    
    original_list[2][0] = 100
    print(original_list)  # [1, 2, [100, 4]]
    print(deep_copy)      # [1, 2, [3, 4]]

     

    sqlite3

    import sqlite3
    
    # 데이터베이스 연결 및 테이블 생성
    conn = sqlite3.connect('example.db')
    
    # SQL 문 실행 
    cursor = conn.cursor()
    cursor.execute('''CREATE TABLE IF NOT EXISTS users
                    (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)''')
    
    # 데이터 삽입
    cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ('John Doe', 30))
    conn.commit()
    
    # 데이터 조회
    cursor.execute("SELECT * FROM users")
    rows = cursor.fetchall()
    for row in rows:
        print(row)
    
    # 데이터 업데이트
    cursor.execute("UPDATE users SET age = ? WHERE name = ?", (31, 'John Doe'))
    conn.commit()
    
    # 데이터 삭제
    cursor.execute("DELETE FROM users WHERE name = ?", ('John Doe',))
    conn.commit()
    
    # 연결 종료
    conn.close()

    모듈 검색 경로

    import sys
    
    print(sys.path)
    '''
    ['C:\\Users\\airyt\\PycharmProjects\\pythonProject1\\modules', 
    'C:\\Users\\airyt\\PycharmProjects\\pythonProject1', 
    'C:\\Users\\airyt\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip', 
    'C:\\Users\\airyt\\AppData\\Local\\Programs\\Python\\Python310\\DLLs', 
    'C:\\Users\\airyt\\AppData\\Local\\Programs\\Python\\Python310\\lib', 
    'C:\\Users\\airyt\\AppData\\Local\\Programs\\Python\\Python310', 
    'C:\\Users\\airyt\\PycharmProjects\\pythonProject1\\venv', 
    'C:\\Users\\airyt\\PycharmProjects\\pythonProject1\\venv\\lib\\site-packages']
    '''
    파이썬은 임포트 하려면 모듈을 찾기 위해서 특정 경로들을 살핀 후, 여기에 없으면 에러가 뜸.
    
    현재 area.py와 run.py와 같은 폴더에 있어서 area모듈을 불러올 수 있었음.
    'C:\\Users\\airyt\\PycharmProjects\\pythonProject1\\modules'를 제외한 나머지 것들은 
    파이썬이 디폴트로 정해주는 경로임.
     
    C:\\Users\\airyt\\PycharmProjects\\pythonProject1\\venv\\lib\\site-packages'
    외부 패키지는 이 폴더에 저장됨.

    모듈 검색 경로에 새로운 경로 추가하기

    일시적인 추가

    sys.path가 리스트이기 때문에 append를 이용하여 새로운 경로를 추가할 수 있음.

    import sys
    
    sys.path.append(r'C:\Users\airyt\Desktop')
    print(sys.path)  
    '''
    ['C:\\Users\\airyt\\PycharmProjects\\pythonProject1\\modules', 
    'C:\\Users\\airyt\\PycharmProjects\\pythonProject1', 
    'C:\\Users\\airyt\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip', 
    'C:\\Users\\airyt\\AppData\\Local\\Programs\\Python\\Python310\\DLLs', 
    'C:\\Users\\airyt\\AppData\\Local\\Programs\\Python\\Python310\\lib', 
    'C:\\Users\\airyt\\AppData\\Local\\Programs\\Python\\Python310', 
    'C:\\Users\\airyt\\PycharmProjects\\pythonProject1\\venv', 
    'C:\\Users\\airyt\\PycharmProjects\\pythonProject1\\venv\\lib\\site-packages', 
    'C:\\Users\\airyt\\Desktop']
    '''
    print(sys.path[-1])  # C:\Users\airyt\Desktop
    
    
    import my_test
    a = my_test.testfile(3, 4)
    print(a)  # 7
    print(sys.path[-1])  # C:\Users\airyt\Desktop

    원래 파일 이름을 test.py로 했더니 오류나서 my_test.py로 변경함.

    파이썬 내장 모듈이나 다른 사용자 정의 모듈과 이름이 충돌할 수 있어서 그럴 수 있다고 함.

     

    영구적인 추가


    스크립트와 모듈

    파일 내용으로 구별한 것임.
    스크립트 : 프로그램을 작동시키는 코드를 담은 실행 용도의 파일 (run.py)
    모듈 : 프로그램에 필요한 변수들이나 함수들을 정의해 놓은 파일
    모듈은 직접실행하지 않고 다른 파일에서 가져다 와서 씀 (area.py)

    모듈을 임포트하면 모듈 안에 있는 모든 코드가 실행됨.
    이 모듈을 가져오고 싶은데 이 밑의 코드는 실행하고 싶지 않으려면?

    → __name__ 이라는 특수변수를 사용하면 됨.

     

    name은 모듈의 이름을 저장해 놓은 변수
    name의 값은 파이썬에서 알아서 정해줌.
    파이썬 파일을 직접 실행하면 그 파일의 name은 main으로 설정됨.
    파일을 다른 곳에서 임포트해서 사용하면 name은 원래 모듈 이름으로 설정됨.

    area파일을 직접 실행하면 are파일의 name은 main으로 설정됨.
    다른 곳에서 불러와서 사용하면 name = area가 됨.

     

    ### area.py
    print('area 모듈 이름: {}'.format(__name__))
    # area 모듈 이름: __main__
    
    ### run.py
    print('run모듈 이름: {}'.format(__name__))
    # run모듈 이름: __main__
    # area 모듈 이름: area
    print('area 모듈 이름: {}'.format(__name__))
    
    PI = 3.14
    
    def circle(radius):
    	"""원의 넓이를 구하는 함수"""
    	return PI * radius * radius
    
    def square(length):
        """정사각형 넓이를 구하는 함수"""
        return length * length
    
    
    if __name__ == '__main__':  # 파일이 직접 실행되었는지 확인
        # circle과 square을 제대로 사용했는지 확인
        print(circle(2) == 12.56)  # True
        print(circle(5) == 78.5)  # True
        print(square(2) == 4)  # True
        print(square(5) == 25)  # True
    ### area.py
    
    PI = 3.14
    
    # 원의 면적을 구해 주는 함수
    def circle(radius):
        return PI * radius * radius  
    
    # 정사각형의 면적을 구해 주는 함수
    def square(length):
        return length * length
    
    # 함수들을 테스팅 하는 메인 함수
    def main():
        # circle 함수 테스트
        print(circle(2) == 12.56)
        print(circle(5) == 78.4)
    
        # square 함수 테스트
        print(square(2) == 4)
        print(square(5) == 25)
    
    if __name__ == '__main__':
        main()
    ### run.py
    
    import area
    
    # 면적 계산기 프로그램
    def main():
        x = float(input('원의 지름을 입력해 주세요: '))
        print('지름이 {}인 원의 면적은 {}입니다.\n'.format(x, area.circle(x)))
    
        y = float(input('정사각형의 변의 길이를 입력해 주세요: '))
        print('변의 길이가 {}인 정사각형의 면적은 {}입니다.'.format(y, area.square(y)))
    
    if __name__ == '__main__':
        main()

    2. 패키지

     

    import shapes.volume
    
    print(shapes.volume.cube(3))  # 27
    import shapes.volume as vol
    
    print(vol.cube(3))  # 27
    from shapes.area import square
    
    print(square(3))  # 9

    import <package.module>
    run.py
    
    import shapes.volume
    print(shapes.volume.cube(3))
    
    ###################################
    
    import <package> # -----> __init__을 이용하여야 함.
    run.py
    
    import shapes
    print(shapes.volume.cube(3)) # 오류
    
    ###################################
    
    from <package> import <module(s)>
    run.py
    
    from shapes import volume
    print(volume.cube(3))
    
    ###################################
    
    from <package.module> import <member(s)>
    run.py
    
    from shapes.volume import cube
    print(cube(3))

    이미지를 비트맵 형식으로 표현

    # 이미지 합성
    def merge(img1, img2):
        # img1과 img2의 크기가 같은지 확인
        if get_size(img1) == get_size(img2):
        	# new_img 리스트 초기화 (안 하면 접근 불가)
            new_img = [[0 for _ in range(len(img1[0]))] for _ in range(len(img1))]
            # 리스트에 원소 대입
            for i in range(len(img1)):
                for j in range(len(img1[i])):
                    if img1[i][j] == 1 and img2[i][j] == 1:
                        new_img[i][j] = 1
                    elif (img1[i][j] == 0 and img2[i][j] == 1) or (img1[i][j] == 1 and img2[i][j] == 0):
                        new_img[i][j] = 1
                    elif img1[i][j] == 0 and img2[i][j] == 0:
                        new_img[i][j] = 0
            return new_img
        else:
            print('img1과 img2의 크기가 같아야 합니다!')

    힘들게 코드까지 짜놓았는데, 문제를 다시 읽어보니 사용할 수 있는 함수가 있었음.

     

    # 이미지 합성
    def merge(img1, img2):
        # img1과 img2의 크기가 같은지 확인
        if get_size(img1) == get_size(img2):
            [height, width] = get_size(img1)
            new_img = empty_image(height, width)
            for i in range(height):
                for j in range(width):
                    new_img[i][j] = or_bits(img1[i][j], img2[i][j])
            return new_img
        else:
            print('img1과 img2의 크기가 같아야 합니다!')
    # 비트 합성
    def or_bits(bit1, bit2):
        return min(1, bit1 + bit2)
    # -1로 채워진 새로운 이미지 생성
    def empty_image(height, width):
        new_img = []
        for i in range(height):
            new_img.append([-1] * width)
        return new_img

     


    3. 외부 패키지 사용하기

     

    728x90