본문 바로가기

1. Python

3/9(목) IT K-DT (6일차) / 12.사용자정의함수~16.객체지향과클래스

 

12. 사용자 정의 함수

 

12-1. 함수

 

12-1-3. 리턴값이 있는 함수

 


def 함수명(변수1, 변수2,  ...) :
    함수가 호출되면 실행할 문장
    ...
    return 값 

# 돌아온 값을 변수에 저장하고 싶다면, return을 사용


함수명(값1, 값2 ...)
# 기존에 함수를 호출하는 방법

 

def func4():
  print('안녕하세요 파이썬') # return값이 없고, 실행하면 바로 출력됨.


안녕하세요 파이썬

 

a = func4()
print(f'a에 저장된 값:{a}') 
# 저장된 값이 None으로 출력. func4()에 return값이 없기 때문.


a에 저장된 값:None

def func5():
  return '💎'
presents = func5()
print(f'presents에 저장된 값:{presents}') 
# func5()에 return값이 있으므로, 저장된 값이 출력됨.


presents에 저장된 값:💎

def func6(num1, num2):
  sum = num1 + num2
  return(sum) 
# num1, num2, sum은 func6()함수 안에서만 사용되는 변수이다. 
# (define되지 않아 func6() 외부에서는 사용할 수 없음.)
result = func6(10,5)
print(result)


15

def test1():
  print('안녕하세요')


안녕하세요

def test2():
  return '안녕하세요' 
# return의 형태가 코드를 작성할 때 유연한 작성이 가능하기 때문에 더 많이 사용됨.
print(test2())


안녕하세요

 

12-1-4. 디폴트 매개변수

 


def 함수명(변수1=값1, 변수2=값2...):
    함수가 호출되면 실행할 문장
    ...
    return 값


변수 = 함수명(값1, 값2 ...)
변수 = 함수명() 


 

호출값을 따로 지정하지 않는다면, 기본적으로 들어있는 값이 출력됨.
디폴트 매개변수는 첫번째 파라미터에만 적용할 수 없음.

def func6(num1=1, num2=1): 
# 값1의 디폴트값은 항상 입력이 되어있어야 한다. 값2부터는 생략이 가능.
  sum = num1 + num2
  return sum
  
print(func6())


2

print(func6(10,5))


15

result = func6(7,3)
print(result)


10


12-1-5. 매개변수의 개수가 가변적인 함수

 


def 함수명(*변수):
    함수가 호출되면 실행할 문장
    ...
    return 값


변수 = 함수명(값1, 값2 ...) 
변수 = 함수명(값1)
변수 = 함수명()



가변적인 매개변수를 전달할 경우 함수 안에서 튜플형태로 사용하게 된다.

def func7(*args): # args : 인자의 개수가 고정되지 않은 매개변수를 작성할 때 사용
    result = 0
    print(args)


()

print(func7(10,30,70,20))


(10, 30, 70, 20)

 

print(func7())를 작성하여 실행할 시,3번줄의 print(args)가 이미 작성되어있기 때문에 
return값이 없어서 None이 출력됨. 

def func8(*args):
    result = 0
    for i in args:
        result += i
        return result      
print(func8(10,30,70,20))


130


12-1-6. 매개변수를 딕셔너리 구조로 전달받는 함수

 


def 함수명 (**변수):
    함수가 호출되면 실행할 문장
    ...
    return 값
변수 = 함수명(변수1=값1, 변수2=값2...) 

 

def func9(id, name, age):
  print(f'아이디:{id}')
  print(f'이름:{name}')
  print(f'나이:{age}')

dic1 = {'id':'apple', 'name':'김사과', 'age':20}
# 매개변수명과 딕셔너리의 key가 같아야 함. 순서도 같아야 함.
# 딕셔너리의 key는 반드시 문자열 형태여야 함.

func9(**dic1)


아이디:apple
이름:김사과
나이:20

 

print()를 앞에 씌우면, None이 같이 출력.
*를 2개를 사용할 경우, value값이 출력.

func9(*dic1)

 

아이디:id
이름:name
나이:age

 

*를 1개만 쓸 경우, key값이 출력.

def func10(**args):
  for i in args:
    if i == 'id':
      id = args[i]
  return id
user = func10(id='apple', name='김사과', age=20)
print(user)


apple

 

12-1-7. 리턴값이 여러개인 함수



def 함수명(변수1, 변수2 ...):
    함수가 호출되면 실행할 문장
    ...
    return 값1, 값2, ...
변수1, 변수2, ... = 함수명(변수1, 변수2, ...) 

 

def func11(num1, num2):
  return num1 + num2, num1 - num2, num1 * num2, num1 / num2

result1, result2, result3, result4 = func11(10,3)
print(f'덧셈 : {result1}, 뺄셈 : {result2} , 곱셈 : {result3}, 나눗셈 : {result4}')


덧셈 : 13, 뺄셈 : 7 , 곱셈 : 30, 나눗셈 : 3.3333333333333335

result1, result2, result3, result4 = func11(10,3) 중에서 result3인 곱셈부분만 필요한 경우, 사용하지 않는 위치에 '언더바(_)

 

_, _, result3, _ = func11(10,3)
print(result3)

 

30

 

13. 변수의 범위

 

13-1. 스코프(scope)

 

변수가 접근할 수 있는 범위


local : 함수 안의 범위
global : 함수 밖의 변수 또는 import된 module

 

num1 = 10 # global 변수 (함수 밖의 변수)

def func1():
  num2 = 20 # local 변수 (함수 안의 변수)
  print(num2)

print(num1)
# 함수 밖에서 print(num2)를 실행하면 에러 발생. NameError: name 'num2' is not defined
func1()


10
20

locals() : local 변수를 확인해주는 함수
globals() : global 변수를 확인해주는 함수

num1 = 10

def func1():
  num2 = 20
  print('num1 로컬 변수 : ', 'num1' in locals()) 
print(func1())


num1 로컬 변수 :  False
None

def func2():
  num2 = 20
  print('num2 로컬 변수 : ', 'num2' in locals())
print(func2())


num2 로컬 변수 :  True
None

def func3():
  print('num1 글로벌 변수 : ', 'num1' in globals())
print(func3())


num1 글로벌 변수 :  True
None

num1 = 10 # 전역 변수
def func4():
  num1 = 20 # 지역 변수
  print(num1)
print(func4()) # 함수를 출력할 때는 지역변수가 우선.


20
None

 

print(num1) # 지역변수는 함수를 벗어나는 순간 사용을 할 수 없기 때문에, 전역변수가 출력됨.


10

 

 

13-2. global

함수 내부에서 local 변수가 아닌 global 변수로 사용하게 해줌.

num1 = 10 
def func5(): 
  print(num1)
func5()


10

def func6(num):
  num1 = num # local 변수에 값을 저장했으므로 global 변수에 값이 변경되지 않음.
func6(5)
func5()

 

10


func6(5)를 출력하여 num에 5를 보내고 num=num1로 저장을 하였으나, 
num1은 지역변수이기 때문에 5가 아니라 10이 출력이 됨.

num1 = 10 

def func5(): 
  print(num1)
  
def func6(num):
  global num1 # global num1을 작성해주면 num1이 global 변수로 변경이 되므로, 5가 정상적으로 출력이 가능해짐.
  num1 = num
func5()


10

 

func6(5)
func5()


 

# 위의 내용과 다르게 10이 아니라 5가 출력이 되는 것을 볼 수있음.

 

14. 콜백함수와 람다함수

 

14-1. 콜백함수(Callback Function)

직접 호출하는 것이 아닌 다른 함수에 의해 호출되는 함수

 

def callback_func(func): # func : 임의의 매개변수화 된 함수
  for i in range(5): # 전달받은 func()를 함수화시켜서 돌릴예정
      func()
def print_hello():
  print('안녕하세요 파이썬')

print_hello()


안녕하세요 파이썬

 

callback_func(print_hello)



안녕하세요 파이썬
안녕하세요 파이썬
안녕하세요 파이썬
안녕하세요 파이썬
안녕하세요 파이썬

def callback_func(func):
  for i in range(5):
    func(i)
def print_hello(num):
  print('안녕하세요 파이썬', num)
callback_func(print_hello)


안녕하세요 파이썬 0
안녕하세요 파이썬 1
안녕하세요 파이썬 2
안녕하세요 파이썬 3
안녕하세요 파이썬 4

 

14-2. 람다 함수 (Lambda Function)

단일문으로 표현되는 익명의 함수 (함수를 가리키는 변수가 없음)
코드상에서 한번만 사용되는 기능이 있을 때, 굳이 함수를 만들지 않고 일회성으로 만들어 사용 

(함수는 클래스를 통해 생성된 객체)
무조건 return의 형태
장점 : 메모리의 절약이 가능함. (함수역할이 끝나면 메모리에서 사라짐)

 

1) 일반적으로 정사각형을 구하는 함수를 사용할 때

 

def square(x):
  return x**2
print(square(4))


16

2)람다 함수를 사용할 때

 

lambda x: x ** 2 # 무조건 return의 형태이므로 따로 return을 작성하지 않음
# 실행하면 함수 형태의 객체가 됨. <function __main__.<lambda>(x)>
square = lambda x: x ** 2 # 람다함수에 대한 설명을 위해 작성한 것이지, 실제로 이런식으로 사용되지는 않음.
print(square(4))


16

 

(lambda x: x ** 2)(4) # 실제로 이런식으로도 사용되지 않음.


16

def myData(string): # 'string'은 변수의 이름.
  return len(string.strip()) # strip() : 양 옆의 공백을 제거하는 함수.
print(myData('apple'))


5

 

# myData의 함수를 사용해서 오름차순으로 정렬하여 출력. 'key'를 사용.
data = ['watermelon', '    apple    ', '        banana', 'avocado']
print(sorted(data, key=myData))


['    apple    ', '        banana', 'avocado', 'watermelon']

# 람다함수를 사용하여 위의 식을 변경
print(sorted(data, key=lambda string:len(string.strip())))


['    apple    ', '        banana', 'avocado', 'watermelon']


14-2-1. 람다가 유용하게 사용되는 함수

filter():

특정 조건을 만족하는 요소만 남기고 필터링시키는 함수

 

li = [1, 2, 3, 4, 7, 9, 14, 15, 19, 20]
result = filter(lambda n:n%2==0, li)
# 여기서 print(result)을 입력하면 <filter object at 0x7fdd405c56a0>가 출력. 반환되는 객체의 표현.

# 개별 요소에 접근하려면 for 루프나 list() 등의 함수를 사용하여 명시적으로 객체를 반복해야 함.
result = list(filter(lambda n:n%2==0, li)) # li의 갯수만큼 filter함수가 콜백해서 호출함.
print(result)


[2, 4, 14, 20]

def even(n):
  if n%2==0:
    return True
  else:
    return False
result = list(filter(even, li)) 

# even()이 아니라 even만 사용해도 정상적으로 출력이 됨. filter()가 콜백함수라는 의미.
print(result)


[2, 4, 14, 20]

map():

각 원소를 주어진 수식에 따라 변형하여 새로운 값을 반환시켜주는 함수

 

li = [1, 2, 3, 4, 7, 9, 14, 15, 19, 20]
per = map(lambda n:n*0.01, li)
# 여기서 print(per)을 입력하면 <map object at 0x7fdd405c56a0>가 출력. 반환되는 객체의 표현.
# 개별 요소에 접근하려면 for 루프나 list() 등의 함수를 사용하여 명시적으로 객체를 반복해야 함.
per = list(map(lambda n:n*0.01, li))
print(per)


[0.01, 0.02, 0.03, 0.04, 0.07, 0.09, 0.14, 0.15, 0.19, 0.2]

def percent(n):
  return n * 0.01
per = list(map(percent, li)) 
# percent()이 아니라 percent만 사용해도 정상적으로 출력이 됨. map()가 콜백함수라는 의미.
print(per)


[0.01, 0.02, 0.03, 0.04, 0.07, 0.09, 0.14, 0.15, 0.19, 0.2]

 

15. 랜덤 모듈

임의의 숫자를 무작위로 반환하는 기능을 가진 모듈.

 

 

15-1. random()

0 이상 1 미만의 실수 중에서 무작위로 하나를 뽑아 반환

 

import random

num = random.random()
print(num)

num = num * 10
print(num)

num = int(num) # 0~9까지의 정수가 나올 수 있는 범위
print(num)


0.14205772900829827
1.4205772900829827
1

# 1~10까지의 정수를 무작위로 뽑으려 할 때
num = int(random.random() * 10) + 1
print(num)


2

 

15-2. randrange()

원하는 범위를 입력하여 범위의 무작위 정수를 반환

 

random.randrange(1, 46)


45

 

15-3. shuffle()

자료구조에 저장된 값의 순서를 무작위로 반환

 

li = ['김사과', '반하나', '오렌지', '이메론', '배애리']
random.shuffle(li)
print(li)


['배애리', '반하나', '김사과', '이메론', '오렌지']

 

15-4. choice()

자료구조에 저장된 값 중 하나를 무작위로 반환

li = ['김사과', '반하나', '오렌지', '이메론', '배애리']
random.choice(li)

 

배애리

random.choice([True, False])


False

while True :
  num = int(input('숫자를 입력하세요'))
  if num == 6:
    break


숫자를 입력하세요1
숫자를 입력하세요2
숫자를 입력하세요3
숫자를 입력하세요4
숫자를 입력하세요5
숫자를 입력하세요6

 

16. 객체지향과 클래스

 

16-1. 객체지향 프로그래밍

문제를 여러 개의 객체단위로 나눠 작업하는 방식. 협업과정이 절차지향 프로그램보다 훨씬 유리하다.

 

16-1-1. 객체(Object)란?

물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중 자신의 속성을 가지고 있고 다른 것과 식별 가능한 것을 말함.

 

16-1-2. 클래스(Class)란?

객체를 생성하기 위한 일종의 설계도.
클래스는 property(필드), method(함수)로 구성되어 있음.
property : 데이터가 저장되는 곳
method : 객체의 동작에 해당하는 실행 블록.
클래스의 이름 첫 글자는 항상 대문자를 사용.

 

16-1-3. 클래스와 객체

건축 설계도가 클래스라면, 실제로 지어진 집은 객체이다.
객체는 클래스로 생성되어 구체화된 instance이다.
실제로 클래스가 instance화 되어 메모리에 상주하는 형태를 객체라고 부름.
파이썬의 모든 변수와 함수는 객체로 저장되어 있음.

 


객체(object)와 인스턴스(instance)의 차이
클래스로 만든 객체를 인스턴스라고도 함.

그렇다면 객체와 인스턴스의 차이는?
a = Cookie() 에서, a는 객체이다. 그리고 a 객체는 Cookie의 인스턴스이다.
즉 인스턴스라는 말은 특정 객체(a)가 어떤 클래스(Cookie)의 객체인지를 관계 위주로 설명할 때 사용함.
"a는 인스턴스"보다는 "a는 객체"라는 표현이 어울리며
"a는 Cookie의 객체"보다는 "a는 Cookie의 인스턴스"라는 표현이 훨씬 잘 어울린다.

 

16-2. 클래스 만들기

 


class 클래스명:

  property명1 = 값1
  property명2 = 값2
  ...
  def 메소드명1(변수1, 변수2...):
      메소드가 호출되면 실행할 문장
      ...
  def 메소드명2(변수1, 변수2...):
      메소드가 호출되면 실행할 문장
      ...



클래스를 통해 호출되는 변수를 property(필드)라고 부름.
클래스를 통해 호출되는 함수를 method라고 부름.


static :
클래스를 정의할 때 사용되는 키워드. 클래스 멤버는 클래스 자체에 속하는 속성(Attribute)이나 메서드(Method)로서,

클래스의 모든 객체에서 공유됨. static 키워드를 사용하여 정의된 클래스 멤버는 해당 클래스의 모든 객체에서 공유되며, 객체가 생성되지 않아도 클래스 이름으로 직접 접근할 수 있음.

 


self :
클래스 내부의 메서드(method)에서 사용되는 특별한 매개변수로, 해당 클래스의 인스턴스(Instance)를 가리키는 참조. 
클래스의 인스턴스를 가리키는 참조이므로, 해당 클래스의 인스턴스 변수에 접근하거나,
다른 메서드(method)를 호출할 때 사용됨. (출처를 알리기 위한 목적)


 

 

# 내용이 없는 블록을 만들 때 사용하는 키워드. 나중에 구현하겠다는 의미로 오류가 발생하지 않음.

 

class Dog:
    pass

 

# 클래스를 통해 객체를 생성
Rucy = Dog()
print(Rucy)
print(type(Rucy))


<__main__.Dog object at 0x7fca3f636490>
<class '__main__.Dog'>

 

<class '__main__.Dog'>가 출력, Dog이라는 class에 만들어졌다는 것을 의미함. 

PPomi = Dog()
print(PPomi)
print(type(PPomi))


<__main__.Dog object at 0x7fca3f593eb0>     # Rucy와 같은 class이나, 객체에서는 서로 다른 메모리주소를 가짐. 

<class '__main__.Dog'>    # <class '__main__.Dog'>가 출력, Dog이라는 class에 만들어졌다는 것을 의미함. 

class Dog:
  name = '루씨'
  age = 13
  family = '포메'
  def eat(self):
  # self라는 매개변수가 소괄호 안에 없으면 출력할 때 에러가 발생.
  # TypeError: eat() takes 0 positional arguments but 1 was given
    print(self)
    
    # 누가 호출했는지에 대한 메모리주소가 출력됨. 
    # self를 사용하지 않으면 다른 property에서 사용할 수 없음.
    print('사료를 먹습니다.')
    
Rucy = Dog()
print(Rucy.name)
print(Rucy.age)
print(Rucy.family)
# 점을 찍을때 팝업된 리스트 중 파란 아이콘이 property, 보라 아이콘이 method이다.

Rucy.eat()


루씨
13
포메
<__main__.Dog object at 0x7fca3f4f32b0>
사료를 먹습니다.

 

PPomi = Dog()
print(PPomi.name)
print(PPomi.age)
print(PPomi.family)

PPomi.eat()
print(PPomi)


루씨
13
포메
<__main__.Dog object at 0x7fca3f4f3ee0>
사료를 먹습니다.
<__main__.Dog object at 0x7fca3f4f3ee0>

 

 

16-3. 생성자(Constructor)

class를 객체화 시킬 때 가장 먼저 자동으로 실행되는 method.


__ init __(self)

 

special method라고 부름. 실제로는 중간에 공백이 있으면 안됨.

생성자에서는 해당 class가 다루는 데이터를 정의하고 초기화함.

 

class Dog:
  def __init__(self): 
    print(self, 'init 호출') # 생성자가 추가된 상황

Rucy = Dog() # 생성자가 있기 때문에 객체만 생성해도 자동으로 출력됨.

 

class Dog:
  def __init__(self): 
    self.name = '이름없음'
    self.age = 0
    
Rucy = Dog()

print(Rucy)
print(Rucy.name)
print(Rucy.age)


<__main__.Dog object at 0x7fca3f6374f0>

이름없음
0

PPomi = Dog()
print(PPomi)
print(PPomi.name)
print(PPomi.age)


<__main__.Dog object at 0x7fca3f637340>
이름없음
0

Rucy.name = '루시'
Rucy.age = 13
PPomi.name = '뽀미'
PPomi.age = 7

print(Rucy)
print(Rucy.name)
print(Rucy.age) 
# 메모리주소는 같으나, name과 age가 다름.


<__main__.Dog object at 0x7fca3f6374f0>
루시
13

print(PPomi)
print(PPomi.name)
print(PPomi.age) 
# 메모리주소는 같으나 name과 age가 다름.


<__main__.Dog object at 0x7fca5c926c10>
뽀미
7

class Dog:
  def __init__(self): 
    self.name = '이름없음'
    self.age = 0
    nickname = '닉네임없음' # 메소드 안에서만 사용할 수 있는 지역변수
    print(f'{nickname} 객체가 생성됨')
  def go(self):
    print(f'{self.name}가 달립니다')
    
# print(f'{nickname}가 달립니다') 라고 작성하면, 오류가 발생.
# nickname이 메소드 안에서만 사용할 수 있는 지역변수이기 때문임.

Rucy = Dog()
Rucy.name = '루시'
Rucy.go()


닉네임없음 객체가 생성됨
루시가 달립니다

# 위의 지역변수인 nickname을 사용해서 작성을 하고 싶은 경우

class Dog:
  def __init__(self): 
    self.name = '이름없음'
    self.age = 0
    self.nickname = '닉네임없음'
  def go(self):
    print(f'{self.nickname}이 달립니다')
    
Rucy = Dog()
Rucy.name = '루시'
Rucy.go()


닉네임없음이 달립니다

# 생성자를 사용하여 작성하고 싶은 경우

class Dog:
  def __init__(self, name, age, nickname='닉네임없음'):
    self.name = name
    self.age = age
    self.nickname = nickname
Rucy = Dog()

# 매개변수를 보내지 않아 에러가 발생함. 
# TypeError: __init__() missing 2 required positional arguments: 'name' and 'age'
Rucy = Dog('루시', 13)

print(Rucy.name)
print(Rucy.age)
print(Rucy.nickname)

 

루시
13
닉네임없음

PPomi = Dog('뽀미', 7)
print(PPomi.name)
print(PPomi.age)
print(PPomi.nickname)


뽀미
7
닉네임없음