[추 Node] 객체지향 프로그래밍 파이썬

데이터 여행자·2021년 2월 14일
1

스터디

목록 보기
1/15
  • 추천 공부 순서: F3(2-8) → F13(6-13) →중첩함수와 재귀함수 → F10(1-9, 9번 코드 이해!)

  • 핵심주제

    • 객체지향
    • 클린코드(중요!)

  1. 객체지향 기초?

  2. 클래스와 상속?


[F-03] 함수

  • 전역 스코프(global scope) 를 갖는 변수: 코드 어디에서든 참조 가능한 변수
  • 지역 스코프(local scope) 를 갖는 변수: 함수 내부에서 정의된 변수
  • 인자(argument): 함수의 입력값, 매개변수에 들어가는 인자('Sam')
  • 매개변수(parameter): 인자를 받는 변수(name)
   def function(name):
       print('Hi' + name)
    
   function('Sam')
  • 함수가 받을 매개변수의 기본값을 지정해주면 입력값이 없을 경우, 기본값을 사용한다. 입력값이 여러 개일 때도 각 입력값마다 기본값을 지정해줄 수 있다. 주의할 점은 기본값이 없는 필수 인자 뒤에 기본값이 있는 인자가 와야 한다는 것이다. (예: (thing1, thing2='anything'), 순서 주의!)
   def default_func(thing='anything'):
       print('Let's do' + thing + '!')

  default_func('it')
  default_func()

결과
Let's do it!
Let's do anything!

  • return: 함수가 실행된 후 그 결과로 무엇인가를 하기 위해서는 return 값을 출력값으로 반환해야 한다.

  • 다음 코드의 결과는? (결과는 맨 아래에 있음)

   def print_two(word1, word2):
       print(word1)
       print(word2)

   def print_and_return(word1, word2, word3):
       print_two(word3, word2)
       return word1

   print_two('A', print_and_return('B', 'C', 'D'))

[F-13] 함수, 람다표현식, 클래스, 프로그래밍 패러다임

6-7. 함수

함수는 코드의 효율성, 재사용성, 가독성을 높여준다.

  • pass: 에러 방지용으로 사용
def func():
   pass
  • 함수에 함수 사용
  • 함수 내 함수, 2개 이상의 return

8. 람다 표현식

이름이 없는 함수.

result = list(map(lamda x: x*3, [1, 2]))
print(result)

참고: 위키독스: 람다

9. 클래스, 모듈, 패키지

  • 클래스
  • 모듈
    함수, 변수, 클래스를 모은 파일. 만들어진 모듈을 가지고 올 수도 있고 직접 만들 수도 있다.
   import 모듈명          # 모듈명 as 약자
   
   모듈명.함수이름(인자)   # 약자가 있다면 '약자.함수이름(인자)'
  • 패키지
    여러 모듈을 모은 폴더.pip 명령어를 사용해 설치 가능.

함수 ⊂ 모듈 ⊂ 패키지

10. 함수형 프로그래밍

  • 절차 지향 프로그래밍
    일이 진행되는 순서대로 프로그래밍하는 방법. 코드가 순차적으로 작성되어 이해는 쉬우나 하나가 잘못되면 연쇄적으로 문제가 생겨서 유지보수가 어렵다. 코드의 길이가 길다.

  • 객체 지향 프로그래밍(OOP, Object Oriented Programming)
    프로그램을 상호작용하는 객체들의 집합으로 보게 하는 프로그래밍. 객체를 작성하고 함수를 작성하며, 작성된 객체는 객체 간 상호작용이 있다. 코드를 재사용하기 쉽고, 코드 분석이 쉬우며, 아키텍처를 바꾸기 쉽다. 그러나 설계에 많은 시간이 들며, 설계를 잘못하면 전부 바꿔야 할 수도 있다.
    참고: 파이썬 - OOP Part 1. 객체 지향 프로그래밍(OOP)은 무엇인가? 왜 사용하는가?

  • 함수형 프로그래밍의 특징
    함수형 프로그래밍은 함수로 문제를 분해하며, 효율성, 버그 없는 코드, 병렬 프로그래밍 등의 장점이 있다.

함수형 프로그래밍은 객체 지향 프로그래밍의 반대라고 생각할 수 있습니다. 객체는 내부 상태들을 갖고 있으며 이 상태들을 수정할 수 있는 메서드의 호출 모음이 포함된 작은 캡슐이며, 프로그램은 올바른 상태 변경 집합을 구성합니다. 함수형 프로그래밍은 가능한 한 상태 변경을 피하고자 하며 함수 간의 데이터 흐름을 사용합니다. 파이썬에서는 응용 프로그램의 객체를 나타내는 인스턴스(전자 우편 메시지, 트랜잭션 등)를 가져와서 반환하는 함수를 작성함으로써 두 가지 접근 방식을 결합할 수 있습니다. (참고: 함수형 프로그래밍 HOWTO)

  • 순수성
    내부를 수정하거나 함수의 반환값에서 보이지 않는 다른 변경사항을 만드는 부작용이 있는 함수를 사용하지 않는다. 프로그램이 수정될 수 있는 상황을 엄격히 제한하며, 함수의 출력은 입력에만 의존한다.
       # 순수성이 있는 함수
       def pure_add(a, b):
           return a + b
           
       print(pure_add(4, 6))  
  • 모듈성
    문제를 작게 분해하도록 한다. 작은 함수는 가독성이 좋고 오류 확인도 쉽다. 따라서 프로그램은 더욱 모듈화가 된다.

  • 디버깅과 테스트 용이성
    함수형 프로그램으로 개발된 프로그램은 함수가 작고 명확하므로 디버깅을 쉽게 할 수 있다. 프로그램이 동작하지 않으면 각 함수는 확인할 수 있는 포인트가 된다. 각 함수는 단위 테스트의 대상이므로 테스트가 쉽다. 함수의 입력과 출력을 확인하면 되기 때문이다.

11. 파이써닉하게 코드 쓰기

참고자료: [PEP8] Code lay-out
코드 스타일 - The Hitchhiker's Guide to Python

파이썬이 가독성이 뛰어난 이유는 코드 스타일 가이드라인(pep8)과 "파이썬스러운" 이디엄(코드 작성법) 때문이다.

  • whitespace

    • 한 줄의 코드 길이가 79자 이하
    • 함수와 클래스는 다른 코두와 빈 줄 2개로 구분
    • 클래스 내에서 함수는 빈 줄 하나로 구분
    • 변수 할당 앞뒤에 스페이스 하나만 사용
    • 리스트 인덱스, 함수 호출에는 스페이스를 사용하지 않음
    • 쉼표, 쌍점(:), 쌍반점(;) 앞에서는 스페이스를 사용하지 않음)
  • 주석

    • 코드의 내용과 일치하지 않는 주석은 피할 것
    • 불필요한 주석은 쓰지 말 것
  • 이름 규칙

    • 변수명 앞에 _(밑줄)이 있으면 함수 등의 내부에서만 사용하는 변수임
      _list = []

    • 변수명 뒤에 _(밑줄)이 붙으면 라이브러리/파이썬 기본 키워드와의 충돌을 피하고 싶을 때
      import_ = "not_import"

    • 소문자 l, 대문자 O, 대문자 I를 가능하면 쓰지 말 것.

    • 모듈명은 짧은 소문자로 구성, 필요하면 밑줄로 구분
      my_module.py

    • 클래스 명은 파스칼 케이스(PascalCase) 컨벤션으로 작성

     class CreateClass():
           pass
  • 함수명은 소문자로 구성, 필요하면 밑줄로 나눔
  • 상수는 모듈 단위에서만 정의, 모두 대문자, 필요하면 밑줄로 나눔
    My_PI = 3.14
  • 네이밍 컨벤션(Naming Convention)
    • snake_case: 함수, 변수 명명
    • PascalCase(UpperCamelCase, CapWords): 클래스 명명
    • camelCase:(lowerCamelCase): 파이썬에서는 거의 사용 안함

중첩함수와 재귀함수

중첩함수와 재귀함수

지역변수와 코드를 묶어서 사용하고 싶을 때나, 데이터 등을 숨길 때 활용한다.

[F-10] 객체 지향 프로그램, 클래스

객체 지향 프로그램

파이썬의 모든 것(정수, 실수, 데이터 구조, 함수, 프로그램, 모듈 등)은 모두 객체이다.

  • 객체: 속성(attribute -> 변수) + 메소드(method -> 함수)

파이썬에서 정의된 모든 클래스는 Object 클래스를 상속받고 있고 이 클래스가 책임지는 것이 변수 할당과 object id 부여이다.

  • 얕은 복사, 깊은 복사
    얕은 복사란 참조하는 테이터의 id만 복사하는 것이고, 깊은 복사란 원본 객체의 값을 복사하는 것이다.
    • 얕은 복사: copy.copy()
    • 깊은 복사: copy.deepcopy()

클래스

class Car: 
    pass


class Car():
    pass
  • Car와 Car()의 차이: Car라는 클래스는 객체이고, Car()를 호출할 때(클래스의 인스턴스를 할당할 때) Car 타입의 객체가 생성된다.

  • 인스턴스화
    클래스로 객체를 만드는 것. 생성된 인스턴스를 변수에 할당한다. mycar = Car()

  • 속성과 메소드

class Car: 
    name = 'soul'
    color = 'blue'
    
    def drive(self):
        print("driving")
     
    def accelarate(self, speed_up, speed=20):
        self.speed_up = speed_up
        self.current_speed = speed + speed_up
        print('speed up', self.speed_up, 'driving at', self.speed)
        
mycar = Car()
print(mycar.year)    # 속성에 접근
mycar.drive()        # 메소드 호출
mycar.accelarate(5)
  • self
    객체 안에서 self는 클래스에 의해 인스턴스화된 객체 자신이다. 클래스의 메소드는 인자로 self를 받아야 하지만 메소드를 호출할 때는 self를 전달하지 않는다. 인스턴스 변수는 self.를 변수 앞에 붙여 준다. 클래스 메소드 내부에서 self. 없이 선언된 변수는 메소드 내부에서만 사용되므로 self.를 사용해 참조할 수 없다.

  • 생성자 __init__ (던더 이닛 Double Under init, 매직 메소드)
    클래스를 만들 때는 생성자를 사용해 초기화한다.

class Car1: 
    def __init__(self, name, color):
    self.name = name
    self.color = color
    
    def drive(self):
        print("driving")
     
    def accelarate(self, speed_up, speed=20):
        self.speed_up = speed_up
        self.current_speed = speed + speed_up
        print('speed up', self.speed_up, 'driving at', self.speed)
        
 
car1 = Car1('soul', 'blue')   # 클래스를 인스턴스화할 때 __init__ 메소드의 속성의 값 설정
  • 클래스 변수와 인스턴스 변수
class Car: 
    Brand = 'Kia'    # 클래스 변수
    
    def __init__(self.name, color='yellow'):
    self.name = name    # 인스턴스 변수
    self.color = color
  • 클래스 변수: 클레스에 바로 선언된 속성. 클래스로 생성된 모든 객체에서 같은 값을 가진다.
  • 인스턴스 변수: 생성자 안에서 self를 사용해 선언된 변수. 객체가 인스턴스화될 때마다 새로운 값 할당되고, 다른 객체에서는 사용할 수 없다.
  • 상속
    부모 클래스(super class/base class)는 원래 클래스, 자식 클래스(sub class/derived class)는 상속 받은 클래스이다.
    - 메소드 추가
    자식 클래스에 새로운 메소드를 추가할 수 있다.
    • 메소드 재정의(override)
      기존의 메소드를 변경한다. (부모, 자식 클래스에서 모두 가능) 부모 클래스에서 메소드가 변경되었다면 이미 생성된 자식 클래스에서는 적용되지 않는다. (자식 클래스에서 일일이 변경해주어야 함)
class NewCar(Car1):
    # 메소드 추가
    def say(self): 
        print('This is my new car.')
        
    # 메소드 재정의
    def drive(self): 
        print('driving and saying')
  • 부모 메소드 호출
    부모 클래스의 변경사항이 자식 클래스에 반영되도록 부모 메소드를 호출하여 사용한다.
class Car:
    Brand = "Kia"

    def __init__(self, name='soul', color='red'):
        self.name = name
        self.color = color


class NewCar(Car):
    def __init__(self, name, color, category):
        super().__init__(color, category)
        self.maker = maker

newcar = NewCar('sonata','blue', 'Kia')
print(newcar.category)

참고: https://blog.naver.com/ahn_ss75/222176192686
[Python 3.7] 파이썬 클래스 상속 개념과 오버라이딩, super()

F10과 함께 살펴봐야할 튜토리얼

결과
D
C
A
B

0개의 댓글