2021년 1월 21일 목요일

AITech 학습정리-[DAY 4] 파이썬 기초 문법 III

 

=======================

학습내용

Python Object Oriented Programming

파이썬 함수/변수 이름에는 snake_case

파이썬 Class에는 CamelCase


- Attribute 추가는 __init__, self와 함께

__init__은 객체 초기화 예약 함수

- __는 특수한 예약 함수나 변수 그리고 함수명 변경(맨글링)으로 사용

예) __main__ , __add__ , __str__ , __eq__

class SoccerPlayer(object):

    def __init__(self, name, position, back_number):

        # self는 나중에 생성할 인스턴스 자신의 주소. 함수마다 앞에 꼭 붙여야됨.

        self.name = name

        self.position = position

        self.back_number = back_number


    def change_back_number(self, new_number):

        print("선수의 등번호를 변경합니다 : From %d to %d" % \

                    (self. back_number, new_number))

        self.back_number = new_number


    def __str__(self):

        return "Hello, My name is %s. My back number is %d" % \

                    (self.name, self.back_number)


    def __add__(self, other):

        return self.name + other.name


abc = SoccerPlayer("son", "FW", 7)

park = SoccerPlayer("park", "WF", 13)

abc + pack  #  'sonpark'

print(abc)  # "Hello, My name is abc. My back numer is 7"

abc.back_number # 7


OOP characteristics

Inheritance 상속, Polymorphism 다형성, Visibility 가시성


상속


class Person(object): # 또는 class Person: # 부모 클래스 선언

    def __init__(self, name, age):

        self.name = name

        self.age = age


class Korean(Person):

    pass


first_korean = Korean("Sungchul", 35)

print(first_korean.name)

Sungchul


class Person(object): # 또는 class Person: # 부모 클래스 선언

    def __init__(self, name, age, gender):

        self.name = name

        self.age = age

        self.gender = gender


    def about_me(self):

        print(f"저의 이름은 {self.name}이구요, 제 나이는 {self.age}살 입니다.")


    def __str__(self):

        print(f"저의 이름은 {self.name}이구요, 제 나이는 {self.age}살 입니다.")


class Empolyee(Person): # 부모 클래스 Person으로 부터 상속

    def __init__(self, name, age, gender, salary, hire_date):

        super().__init__(name, age, gender)  # 부모객체 사용

        self.salary = salary

        self.hire_date = hire_date


    def do_work(self):

        print("열심히 일을 합니다.")


    def about_me(self):

        super().about_me()

        print(f"제 급여는 {self.salary}원 이구요, 제 입사일은 {self.hire_date} 입니다.")


myPerson = Person("John", 34, "Male")

myEmployee = Empolyee("Daeho", 34, "Male", 30000, "2012/03/01")

myPerson.about_me()

myEmployee.about_me()

저의 이름은 John이구요, 제 나이는 34살 입니다.

저의 이름은 Daeho이구요, 제 나이는 34살 입니다.

제 급여는 30000원 이구요, 제 입사일은 2012/03/01 입니다.


Polymorphism 다형성

- 같은 이름의 메소드의 내부 로직을 다르게 작성

- Dynamic Typing 특성으로 인해 파이썬에서는 같은 부모클래스의 상속에서 주로 발생함

- 중요한 OOP의 개념 그러나 너무 깊이 알 필요X

자바의 오버라이딩 같은거인듯

class Animal:

    def __init__(self, name): # Constructor of the class

        self.name = name

    def talk(self): # Abstract method, defined by convention only

        raise NotImplementedError("Subclass must implement abstract method")

class Cat(Animal):

    def talk(self):

        return 'Meow!'

class Dog(Animal):

    def talk(self):

        return 'Woof! Woof!'

animals = [Cat('Missy'),

           Cat('Mr. Mistoffeless'),

           Dog('Lassie')]

for animal in animals:

    print(animal.name + ": " + animal.talk())

Missy: Meow!

Mr. Mistoffeless: Meow!

Lassie: Woof! Woof!


Visibility 가시성

- 객체의 정보를 볼 수 있는 레벨을 조절하는 것

- 누구나 객체 안에 모든 변수를 볼 필요가 없음

Encapsulation

캡슐화 또는 정보 은닉 (Information Hiding)



Decorator

  • first-class objects
  • inner function ★
  • decorator ★

first-class objects

- 일등함수 또는 일급 객체

- 변수나 데이터 구조에 할당이 가능한 객체

- 파라메터로 전달이 가능 + 리턴 값으로 사용

파이썬의 모든 함수는 일급함수

map(f, ex)

def square(x):

    return x*x

f = square # 함수를 변수로 사용

f(5)


def square(x):

    return x*x

def cube(x):

    return x*x*x

def formula(method, argument_list):

    return [method(value) for value in argument_list]

a = [1, 2, 3, 4, 5]

print(formula(square, a))

print(formula(cube, a))

[1, 4, 9, 16, 25]

[1, 8, 27, 64, 125]


inner function ★

- 함수 내에 또 다른 함수가 존재

def print_msg(msg):
def printer():
print(msg)
printer()

print_msg("Hello, Python")

Hello, Python

- closures : inner function을 return값으로 반환

def func():
def printhi():
print("hi")
return printhi
hiin = func()
hiin()

hi

def print_msg(msg):
def printer():
print(msg)
return printer() ## 에러 !!! ! !!!!

another = print_msg("Hello, Python")
another()
TypeError: 'NoneType' object is not callable
def print_msg(msg):
def printer():
print(msg)
return printer

another = print_msg("Hello, Python")
another()

Hello, Python


def tag_func(tag, text):
tag = tag
text = text

def inner_func():
return '<{0}>{1}<{0}>'.format(tag, text)

return inner_func

h1_func = tag_func('title', 'This is python class')
p_func = tag_func('p', 'Data Academy')
print(h1_func)
print(h1_func())
print(p_func)
print(p_func())

<function tag_func.<locals>.inner_func at 0x000001E19238B0D0>

<title>This is python class<title>

<function tag_func.<locals>.inner_func at 0x000001E19238B160>

<p>Data Academy<p>


decorator function

- 복잡한 클로져 함수를 간단하게! (사실 더복잡함)

def star(func): # func printer(msg)
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner

# @star를 썻기때문에 def star(func) func printer(msg)
@star
def printer(msg):
print(msg)
printer("Hello")

******************************

Hello

******************************

def star(func): # func printer(msg, mark)
def inner(*args, **kwargs):
print(args[1] * 30)
func(*args, **kwargs)
print(args[1] * 30)
return inner

# @star를 썻기때문에 def star(func) func printer(msg, mark)
@star
def printer(msg, mark):
print(msg)
printer("Hello", "&")

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

Hello

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&


def star(func): # func printer(msg)
def inner(*args, **kwargs):
print('*' * 30)
func(*args, **kwargs)
# func
# @percent
# printer("Hello")
print('*' * 30)
return inner

def percent(func):
def inner(*args, **kwargs):
print('%' * 30)
func(*args, **kwargs)
# func
# printer("Hello")
print('%' * 30)
return inner

# 그냥 @는 위에서부터 차례대로 실행된다고 생각하면 편할듯
@star
@percent
def printer(msg):
print(msg)
printer("Hello")

******************************

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Hello

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

******************************


그 다음은 조금 복잡한 함수를 볼거에요 ( = 아주 복잡하다 )

def generate_power(exponent):
def wrapper(f): # @에 매개변수 넣고 싶으면 한번 더 감싸야 한다.
print("in wrapper f : ", f)
def inner(*args):
print("in inner args : ", args)
result = f(*args) # 7**2
return exponent**result # 2**7**2
return inner
return wrapper

@generate_power(2)
def raise_two(n):
return n**2

print(raise_two)
print("----")
print(raise_two(7))

in wrapper f :  <function raise_two at 0x0000018D9027B160>

<function generate_power.<locals>.wrapper.<locals>.inner at 0x0000018D9027B1F0>

----

in inner args :  (7,)

562949953421312



Module and Project

패키지 안에 모듈

모듈은 프로그램에서 작은 프로그램 조각들, 조각들을 모아서 프로그램을 작성함.

패키지를 오픈소스에 공개! 한다는건 프로그램을 공개


모듈 만들기

- 파이썬의 Module == py 파일을 의미

- 같은 폴더에 Module에 해당하는 .py파일과

  사용하는 .py을 저장한 후

- import 문을 사용해서 module을 호출

함수명을 불러서 쓸 수 있다.


namespace

- 모듈을 호출할 때 범위 정하는 방법

- 모듈 안에는 함수와 클래스 등이 존재 가능

- 필요한 내용만 골라서 호출 할 수 있음

- from과 import 키워드 사용함

Alias 별칭 설정하기

import fah_converter as fah

print(fah.convert_c_to_f(41.6)) # 어디서 왔는지 밝힐 수 있음

모듈에서 특정 함수 또는 클래스만 호출하기

from fah_converter import convert_c_to_f

print(covert_c_to_f(41.6)) # 원래 print(fah_converter.covert_c_to_f(41.6)) 해야했음.

모듈에서 모든 함수 또는 클래스를 호출하기

from fah_converter import *

print(covert_c_to_f(41.6))


파이썬 내장 함수 random, time, urllib.request 등이 있음.


패키지

- 하나의 대형 프로젝트를 만드는 코드의 묶음

- 다양한 모듈들의 합, 폴더로 연결됨

- __init__, __main__ 등 키워드 파일명이 사용됨

- 다양한 오픈 소스들이 모두 패키지로 관리됨

각각의 폴더 안에 __init__.py 라는 파일이 있어야 함.

각각 __init__.py 안에 

__all__ = [사용할 파일이름, 사용할 파일 이름, ..]

from . import 사용할 파일이름

from . import 사용할 파일이름

..

그다음 루트폴더에 __main__.py 만들고

from sound import echo

if __name__ == '__main__':

    print("hello game")


오픈소스 라이브러리 사용하기


두개 이상의 프로젝트를 불러오면 충돌할 수도 있다...

가상환경 설정하기

프로젝트 진행 시 필요한 패키지만 설치하는 환경

다양한 패키지 관리도구 사용 virtualenv, conda 등

 

conda create -n my_project python=3.8

conda activate my_project

conda install matplotlib

conda install tqdm

conda install jupyter

import matplotlib.pyplot as plt

plt.plot([1,2,3,4])

plt.ylabel('some numbers')

plt.show()


===============================

과제


이번 모스부호 과제는 아니고 전 baseball 과제였는데 while문을 너무 많이 넣어서 딱 봐도 너무 복잡해 보인다.


딱 봐도 개판이다.

다른 피어분껄 봤는데, 각 경우를 함수로 빼내 사용했다고 한다. 그러니까

flag = False

for i in range(N):

    for j in range(N):

        if (어쩌구):

            flag = True

            break

    if flag :

        break

같은 걸 안했단 것 같다. 나도 이런거 하기 싫어 함수로 만들어 빼낸적이 몇번 있으니까 활용해야 될 것 같다.


=================================

피어세션

데코레이션이 어려워서 어떻게 보면 될지 회의했다. 난 함수 자체를 리턴해서 뒤에 괄호 () 를 붙여 실행시키는 걸로 결론지었다.

예를들면

def a():

    return b

def b():

    print("here")

a()()

하면 

here

이 콘솔에 출력되고 끝난다. 그래서 B = a() 로 하면

a()() == B() 가 되는 개념.


댓글 없음:

댓글 쓰기