본문 바로가기
코딩 연습/파이썬 기초(예제)

파이썬 함수, 클래스, 속성 비공개, 상속 등 알아보기

by good4me 2023. 12. 7.

goodthings4me.tistory.com

파이썬 함수, 클래스, 속성 비공개, 상속

 

파이썬이 배우기 쉬운 개발 언어라고 하지만, 다른 언어와 같이 함수, 클래스, 상속, 오버라이딩 등의 개념도 있고, 특히 클래스라는 개념은 다른 언어와 같기 때문에 난이도가 없는 것은 아닙니다.

 

파이썬의 함수와 클래스, 그리고 상속 드의 개념에 대해 간략하게 정리해서 올려봅니다.

 

파이썬 함수 알아보기

 

▶ 함수란?

함수는 어떠한 값을 입력하면 정의된 절차에 따라 일을 수행한 후 결과물을 내는 것

 

▶ 함수를 사용하는 이유

  • 반복되는 코드의 수를 줄일 수 있음
  • 누군가가 만들어 놓은 기능을 손쉽게 활용할 수 있음
  • 팀 단위로 협업/분업 가능
  • 함수의 코드만 수정하면 실제 사용되는 여러 부분들이 자동으로 수정되므로 유지보수가 용이함

 

 

▶ 함수 생성

# 함수 생성 :def - definition
def plus(a, b):  # a, b는 입력값이며, 매개변수(parameter)라고 함
    return a + b
    
x = 10
y = 5
result = plus(x, y)  # 함수 실행(호출), x,y는 인자(argument)라고 함
print(result)
# 15

 

 

▶ 함수의 형태

## 함수의 형태 알아보기
def func1(x):  # 입력값 O, 결과값 O
    return x + 1

def func2(x):  # 입력값 O, 결과값 x
    print(x)

def func3():  # 입력값 x, 결과값 O
    return 1

def func4():  # 입력값 x, 결과값 x
    print(1)

# 결과값이 None 인 경우 결과값이 존재하지 않음(return 문 없음)

# 매개변수에 특정 값을 지정하여 호출하기
def total(a, b, c): 
    return a + b + c

total(10, 20, 30)
# 60
total(a = 11, b = 22, c = 33)
# 66


# 매개변수에 특정값을 지정하여 셍성하기
def setInfo(name, age, isPass=True):  # isPass는 값이 지정됨
    print(name, age, isPass)

setInfo('kim', 20)
# kim 20 True
setInfo('kim', 20, False)
# kim 20 False

 

 

▣ 연습문제

# 하나의 숫자를 입력받아 홀수, 짝수 여부 판별하는 함수 작성
def is_odd(n):
    print('짝수') if n % 2 == 0 else print('홀수')

is_odd(3)
# 홀수
is_odd(4)
# 짝수

# 1 이상의 정수 N을 입력 받은 후 1 ~ N까지의 합을 구하는 함수 작성
def total_sum(n):
    tot = 0
    for i in range(1, n + 1):
        tot += i
    print(tot)

total_sum(10)
# 55

# 숫자 요소를 가지는 리스트를 입력받은 후 합과 평균을 구하고 반환하는 함수 작성
def calculator(lst):
    tot = 0
    avg = 0
    for n in lst:
        tot += n
    avg = tot / len(lst)
    return tot, avg

calculator([1, 3, 5, 6, 9])
# (24, 4.8)

 

 

▶ 지역변수와 전역변수

  • 전역변수 : 일반적인 변수, 코드 영역 어디서든 사용할 수 있는 변수
  • 지역변수 : 함수 내에서 만든 변수, 함수 내에서만 사용(작동)

 

IT, 전자제품 선물

 

 

def func(a):
    b = a + 2
    return b

print(func(10))
# 12
# print(b)  # NameError: name 'b' is not defined


outer_a = 0  # 전역변수 outer_a
def func(a): 
    outer_a = a + 2  # 지역변수 outer_a
    print('함수 내부:', outer_a) 

func(10) 
print('함수 외부:', outer_a)
# 함수 내부: 12
# 함수 외부: 0


## cf) 함수의 매개변수, 지역변수의 스코프와 for 문의 스코프
def fn(a):
    b = a + 1
    print(b, a)
fn(5)
# 6 5

## a, b 호출
# print(a)  # NameError: name 'a' is not defined
# print(b)  # NameError: name 'b' is not defined
# 위에서 a, b는 지역변수이기 때문에 정의되지 않았다고 나오는 것이고,


for i in range(3):
    print(i)
print(i)  # i는 전역변수
# 1
# 2
# 2

# for 문에서 사용한 변수 i는 전역변수로 취급
# 함수는 변수의 스코프에서 다른 차원의 이야기라 생각해야 함


## 힘수 내부에서 전역변수 만들기
def func(a): 
    global outer_a  # outer_a : 전역변수
    outer_a = a + 2  # outer_a : 전역변수
    print('함수 내부:', outer_a) 
func(10) 
print('함수 외부:', outer_a)
# 함수 내부: 12
# 함수 외부: 12

 

 

▶ 람다(lambda) 함수

  • def와 함수명, 그리고 return문이 없는 함수(익명함수하고 함)
  • def처럼 함수를 생성할 때 사용
  • 함수를 간결하게 한 줄로 만들 때 사용
  • 일회성 함수
def plus(a, b):
    return a + b

print(plus(10, 20))
# 30


# 위 함수를 람다로 변경
plus2 = lambda a, b : a + b
print(plus2(10, 20))
# 30


# 람다함수 자체 실행하는 방법
# - 실행 후 메모리에서 사라짐
(lambda a, b : a + b)(10, 20)
# 30

 

 

▶ 파이썬 내장함수

  • 파이썬 내부에 미리 정의되어 있는 함수로 print, type, int, list,....
  • dir(__builtins__) 통해 확인 가능
 
print(dir(__builtins__))

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BaseExceptionGroup', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EncodingWarning', 'EnvironmentError', 'Exception', 'ExceptionGroup', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__IPYTHON__', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'display', 'divmod', 'enumerate', 'eval', 'exec', 'execfile', 'filter', 'float', 'format', 'frozenset', 'get_ipython', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'repr', 'reversed', 'round', 'runfile', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

 

 

# 파이썬의 주요 내장 함수 연습하기

## 주요 내장함수 알아보기

# abs() : 절대값
print(abs(-1))


# 최대값, 최소값, 합계
print(max([33, 4, 48, 5]))
# 48
print(min([33, 4, 48, 5]))
# 4
print(sum([33, 4, 48, 5]))
# 90


# all : 리스트 값 and 연산
print(all([1, 2, 3]))
# True
print(all([0, 1, 2]))
# False


# any : 리스트 값 or 연산
print(any([1, 2, 3]))
# True
print(any([0, 1, 2]))
# True
print(any([0, [], {}]))
# False


# enumerate : 리스트와 인덱스를 묶어서 반환(tuple), 보통 for 문에서 사용함
for i in enumerate(['a','b','c']):
    print(i)
# (0, 'a')
# (1, 'b')
# (2, 'c')

# enumerate 사용 시 인덱스와 요소를 분리
for i, elem in enumerate(['a','b','c']):  
    print(i, elem)
# 0 a
# 1 b
# 2 c

# enumerate 사용 시 인덱스와 요소를 분리하되 인덱스를 변경
for i, elem in enumerate(['a','b','c'], 1):
    print(i, elem)
# 1 a
# 2 b
# 3 c


# filter : 리스트에서 조건에 맞는 값만 가져옴, 첫번째 전달 인자는 함수임
def is_over_1(x):
    return x > 1

for i in [1, 2, 3]:
    print(f'i={i}, result: {is_over_1(i)}')
# i=1, result: False
# i=2, result: True
# i=3, result: True

# 위 for문을 실행하면, False, True, True가 촐력되는데, 이를 filter를 사용하면 True인 결과만 출력됨
for i in filter(is_over_1, [1, 2, 3]):
    print(i)
# 2
# 3


# id : 파이썬에서 코드 실행 시 값이 저장된 메모리 위치를 알려줌
var = 'python'
id(var)
# 2560540089264


# len : 파이썬 자료형 중 리스트, 문자열 등 iterator의 요소 개수를 알려줌
items = [1, 2, 3, 4, 5]
print(len(items))
# 5

txt = '오늘은 몇일?'
print(len(txt))
# 7


# round : 숫자 반올림 round(number, ndigits=None)
print(round(3.141592, 3))
# 3.142
print(round(3.141592, 0))
# 3.0
print(round(3.141592))
# 3

## cf) 파이썬에서 버림 또는 올림 처리하여 정수 만들기
# math 라이브러리의 floor, ceil을 사용해야 하고, math를 import하고 사용함
import math
print(math.floor(3.141592))
# 3
print(math.ceil(3.141592))
# 4
print(math.trunc(3.141592))
# 3

# floor와 trunc의 차이점 
# - floor는 음의 방향으로 작거나 같은 정수로, trunc는 0 방향 정수로 진행 
math.floor(5.7)  # 5 반환
math.floor(-5.7)  # -6 반환
math.trunc(5.7)  # 5 반환
math.trunc(-5.7)  # -5 반환 (0 방향으로)


# map : 리스트 등 iterator요소를 함수에 적용하여 결과값을 반환.
# - 리스트와 같이 사용하기 때문에 결과는 리스트임
print(map(str, [1, 3, 4]))
# <map object at 0x000002542F39C400>
print(list(map(str, [1, 3, 4])))
# ['1', '3', '4']

res = map(str, (1, 3, 4))
print(res)
# <map object at 0x000002542F3A9F90>
print(list(res))
# ['1', '3', '4']

# 람다 함수와 같이 사용
print(list(map(lambda x: x**2, [2, 3, 4])))
# [4, 9, 16]

 

 

▶ 필터 함수 만들어 보기

## filter 함수 만들기

def filter2(func, items):
    res_list = []
    for i in items:
        result = func(i)
        if result:
            res_list.append(i)
    return res_list

def is_over_1(n):
    return n > 1

print(filter2(is_over_1, [1, 2, 3]))
# [2, 3]

 

 

▶ 파이썬의 외장함수

  • 파이썬에서 외장 함수는 별도의 라이브러리(패키지, 모듈)에 포함된 함수들임
  • 파이썬 내부 라이브러리(표준 라이브러리 : json, csv, re, pickle, math,...), 외부 설치 라이브러리(pandas, matplotlib,...)가 있음
  • 라이브러리 설치는 pip install 사용해서 설치함
  • 외장 함수는 import 문을 사용하여 라이브러리나 모듈을 불러와서 사용함
import datetime as dt

print(datetime.datetime.now())
# 2023-12-06 10:36:36.774734

# 라이브러리를 호출할 때 별칭(as)를 사용하여 그 별칭을 사용할 수 있음
print(dt.datetime.today())
# 2023-12-06 10:37:21.354341


# from ~ import 사용
from datetime import datetime

print(datetime.now())
# 2023-12-06 14:22:09.496540

 

 

파이썬 클래스 알아보기

 

▶ 파이썬 클래스란?

  • 객체지향의 가장 기본적인 개념으로 사물의 관련 속성(모습)과 동작(기능)을 하나의 범주로 묶어 '실세계의 사물(객체)'을 표현함
  • 사물을 분석하여 클래스로 작성(속성, 기능)하는 것을 모델링이라 함. 즉, 클래스는 사물에 대한 모델을 정의하는 개념으로 생각
  • 클래스 멤버 : 클래스를 구성하는 변수, 함수들을 지칭
  • 메서드 : 클래스 내에서 만든 함수이며, 기능을 담당
  • 메서드의 첫번째 인자로 self를 사용하며, self는 클래스 멤버를 표현하는 것으로 다른 말로 '객체 자신'을 의미함
  • 다만, 메서드가 기능만으로 사용할 때는 self를 사용하지 않아도 되며, 이때는 함수(클래스의 함수)로 작동함

 

 

▶ 클래스 생성

# 클래스생성
class Class1:
    def __init__(self): 
        self.var1 = 10
        
    def add(self):  # 메서드
        self.var1 += 10
        
    def run(): # 함수
        lvar = 100  # 함수 run의 지역변수, 인스턴스 생성 시 같이 생성되지 않음
        return lvar
        
# 클래스 호출(인스턴스 생성)
obj1 = Class1()
# print(obj1.run()) # TypeError: Class1.run() takes 0 positional arguments but 1 was given
print(Class1.run())
# 100

 

*cf) run() 함수는
클래스 내부에 정의되어 클래스에 속해 있기는 하지만 클래스나 인스턴스 객체와 직접적인 연관이 없는 로컬 변수를 가지는 단순한 함수이고,

self 매개변수가 없기 때문에 인스턴스의 속성에 접근할 수 없으며,

클래스나 인스턴스와는 독립적으로 처리되는 함수로 클래스의 일반적인 동작이나 특정한 작업을 수행하기 위해 정의된 함수임

 

 

▶ 클래스 멤버 테스트

class ValTest:
    val_1 = 0
    val_4 = 'a'
    
    def __init__(self):
        self.val_1 = 10
        self.val_3 = 30
        
    def add(self):
        self.val_1 += 20
        self.val_2 = 20 # 지역변수
        self.val_4 += 'b'

    def get(self):
        return [self.val_1, self.val_2, self.val_3, self.val_4]

    def cget(cls):
        return ValTest.val_1, ValTest.val_4

    
vt = ValTest()
# print(vt.val_1, vt.val_2, vt.val_3, vt.val_4)  # AttributeError: 'ValTest' object has no attribute 'val_2'

print(vt.val_1, vt.val_3, vt.val_4)
# 10 30 a

vt.add()
print(vt.val_1, vt.val_2, vt.val_3, vt.val_4)
# 30 20 30 ab

print(vt.get())
# [30, 20, 30, 'ab']

print(vt.cget())  # 인스턴스 객체에서 접근 가능
# (0, 'a')

print(ValTest.val_1)
# 0

# print(ValTest.val_2)  # AttributeError: type object 'ValTest' has no attribute 'val_2'
# print(ValTest.val_3)  # AttributeError: type object 'ValTest' has no attribute 'val_3'

print(ValTest.val_4)
# a

 

 

▶ 클래스 생성자 이용한 초기화 방법

## 클래스 생성자를 이용한 속성 초기화 방법 #1
class Student:
    def __init__(self):  # 초기화
        self.num = 1
        self.grade = 3
        self.name = 'kim'
        
    def setNum (self, num):
        self.num = num
        
    def setGrade (self, grade):
        self.grade = grade
        
    def setName (self, name):
        self.name = name
        
s = Student()
print(s.num, s.grade, s.name)

 

IT관련서비스제품

 

## 클래스 생성자를 이용한 속성 초기화 방법 #2
class Student:
    def __init__(self, num, grade, name):
        self.num = num
        self.grade = grade
        self.name = name
        
    def setNum (self, num):
        self.num = num
        
    def setGrade (self, grade):
        self.grade = grade
        
    def setName (self, name):
        self.name = name

s = Student(1, 3, 'kim')
print(s.num, s.grade, s.name)

 

 

▣ 클래스 작성 연습

## class 작성 연습

class Book:
    def __init__(self):
        self.title = ''
        self.price = ''

    def setTitle(self, title):
        self.title = title

    def setPrice(self, price):
        self.price = price

book1 = Book()
book1.setTitle('Python')
book1.setPrice(10000)
print(book1.title, book1.price)
# Python 10000

book2 = Book()
book2.setTitle('Java')
book2.setPrice(10000)
print(book2.title, book2.price)
# Java 10000

 

## 연습 문제
# 아래 코드가 실행되어 결과와 같이 출력될 수 있도록 코드 작성하기
### 출력 결과 ###
# class Product:
#     # 생성자
#     def show_info(self):
#         return f'name = {self.name}, code = {self.code}, count = {self.count}'

# p1 = Product('clock', 'c0001', 500)
# print(p1.show_info())
# p2 = Product('tv', 't0001', 1500)
# print(p2.show_info())

# name = clock, code = c0001, count = 500
# name = tv, code = t0001, count = 1500


class Product:
    def __init__(self, name, code, count):
        self.name = name
        self.code = code
        self.count = count

    def show_info(self):
        return f'name = {self.name}, code = {self.code}, count = {self.count}'

p1 = Product('clock', 'c0001', 500)
print(p1.show_info())
# name = clock, code = c0001, count = 500
p2 = Product('tv', 't0001', 1500)
print(p2.show_info())
# name = tv, code = t0001, count = 1500


# 문제 2
# class Letter:
#     # 생성자 작성, 변수 초기화
#     # write 메소드 작성
#     # show 메소드 작성
# letter1 = Letter()
# letter1.write('가나다라')
# letter1.write('카타파하')
# print(letter1.show())
# letter2 = Letter()
# letter2.write('ABCD')
# letter2.write('WXYZ')
# print(letter2.show())

class Letter:
    def __init__(self):
        self.word = ''

    def write(self, word):
        self.word += word

    def show(self):
        return self.word

letter1 = Letter()
letter1.write('가나다라')
letter1.write('카타파하')
print(letter1.show())
# 가나다라카타파하

letter2 = Letter()
letter2.write('ABCD')
letter2.write('WXYZ')
print(letter2.show())
# ABCDWXYZ


# 문제3
# class Car:
#     # 생성자 작성, 변수 초기화
#     # add_option 메소드 작성
#     # show_option 메소드 작성
# car1 = Car()
# car2 = Car()
# car1.add_option('전동 트렁크')
# car1.add_option('통풍 시트')
# print(car1.show_option())
# car2.add_option('뒷자리 에어백')
# car2.add_option('하이패스')
# print(car2.show_option()


class Car:
    def __init__(self):
        self.opt = []

    def add_option(self, opt):
        self.opt.append(opt)

    def show_option(self):
        return self.opt

car1 = Car()
car2 = Car()
car1.add_option('전동 트렁크')
car1.add_option('통풍 시트')
print(car1.show_option())
# ['전동 트렁크', '통풍 시트']
car2.add_option('뒷자리 에어백')
car2.add_option('하이패스')
print(car2.show_option())
# ['뒷자리 에어백', '하이패스']

 

 

▶ 클래스 비공개 속성 사용하기

 

 

# 멤버 앞에 '__'로 시작할 경우 그 속성 또는 메서드는 비공개로 되고, 외부에서 참조할 수 없음

class Student:
    def __init__(self, num, name, phone):
        self.num = num
        self.name = name
        self.__phone = phone  # 비공개로 만들기
        
    def setNum (self, num):
        self.num = num
        
    def setName (self, name):
        self.name = name
        
    def setPhone (self, phone):
        self.__phone = phone

    def get_phone(self):
        return self.__phone
        
s = Student(1, 'kim', '010-1234-0000')
print(s.num, s.name)
# 1 kim
# print(s.__phone) # 비공개속성은 직접적으로 볼 수 없다
print(s.get_phone())
s.setPhone('010-1234-4567')
# 010-1234-0000
print(s.get_phone())
# 010-1234-4567

 

class Class2:
    def __init__(self, money):
        self.__money = money

    def add(self, money):
        self.__money += money

    def sub(self, money):
        self.__money -= money

    def show(self):
        pw = input('비밀번호 입력> ')
        if pw == '1234':
            print(self.__money)

m = Class2(10000)
m.add(2000)
m.sub(3000)
m.show()

### 실행결과 ###
비밀번호 입력>  1234
9000

 

## 클래스 속성
class Person:
    bag = []

    def put_bag(self, stuff):
        self.bag.append(stuff)

j = Person()
j.put_bag('사과')

m = Person()
m.put_bag('배')

print(j.bag)
# ['사과', '배']
print(m.bag)
# ['사과', '배']

## j, m 객체는 각각 사과, 배를 넣었는데, bag에는 사과와 배가 모두 있다.


class Person:
    bag1 = []  # 클래스 속성
    
    def __init__(self):
        self.bag2 = []  # 인스턴스 속성
        
    def put_bag(self, stuff):
        self.bag1.append(stuff)
        self.bag2.append(stuff)

kim = Person()
park = Person()
kim.put_bag('key')
park.put_bag('wallet')
print(kim.bag1)
# ['key', 'wallet']
print(kim.bag2)
# ['key']
print(park.bag1)
# ['key', 'wallet']
print(park.bag2)
# ['wallet']

 

 

▶ 클래스 상속

  • 부모 클래스(Parent Class)가 가진 속성과 메서드를 유지한채로 자식 클래스(Child Class)를 만들 때 사용
  • 부모 클래스 : 상속의 대상이 되는 클래스, 자식 클래스에게 속성과 메서드를 제공하고 상속되는 클래스의 기반이 됨
  • 자식 클래스 : 부모 클래스로부터 상속을 받아 생성되는 클래스, 속성과 메서드를 상속받아 사용하거나 수정할 수 있음
# 상속의 형태는 
class PatrentClass:
    # 부모 클래스의 속성과 메서드
    pass

# 상속받는 자식클래스
class ChildClass(ParentClass):
    # 부모 클래스의 속성과 메서드 사용
    # 자식 클래스의 추가적인 속성과 메서드 정의
    pass

 

 

# 부모 클래스
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        return f'{self.name} 월월짓는다'
    
# 자식 클래스
class Dog(Animal):
    pass

dog = Dog('ShuShu')
print(dog.speak())
# ShuShu 월월짓는다


# 자식 클래스 기능 추가(부모 클래스는 가지지 않음)
class Dog(Animal):
    def run(self):
        return f'{self.name} 잘 달리네'

dog = Dog('ShuShu')
print(dog.speak())
# ShuShu 월월짓는다
print(dog.run())
# ShuShu 잘 달리네


# 부모 클래스의 기능 재정의(오버라이드)
class Dog(Animal):
    def speak(self):
        return f'{self.name} 멍멍'
    
    def run(self):
        return f'{self.name} 날라가네'
        
dog = Dog('ShuShu')
print(dog.speak())
# ShuShu 멍멍
print(dog.run())
# ShuShu 날라가네

댓글