본문 바로가기

노력/인공지능

6. 파이썬 개인공부 6 (함수)



side effect가 없는 함수 : 수학함수. math functions. pure 함수


mutable 안쓴다.





수학적 함수가 아니다:

  1. 리턴값이 없다.

  

  2. 함수에 넣어서 사용했는데 원래 값이 바뀌어서 나온다.

  

수학적 함수라면 퓨어함수라고 부른다.


first class function이면 값처럼 사용할 수 있다.



값 바뀌는 코드 거의 안쓴다.


a = 1

b = a+1



higher-order functions : 함수를 받아서 함수를 리턴해주는 함수.


map, filter, reduce : 대표적인 higher-order functions


반복의 단점을 극복하기 위해서 for-while 대신에 comp, map, iterator, generator 등을 사용한다.


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

list(map(lambda i:i*i, a))

map(함수이름, 리스트이름) : 이렇게 받는다.




[i*i for i in a]
[1, 4, 9, 16, 25]

같은 문제를 다른 방식으로 사용할 수 있다.

filter는 걸러내는 것.
list(filter(lambda x:x>5, [2,3,4,5,6,7,8]))
[6, 7, 8]

5 이상인 수만 골라내기.



iterator, generator는 lazy하다. comp는 for가 없다.


lazy란 호출할 때마다 값이 툭툭 튀어나오는 것이다.

next(a)

단순반복도 파이썬은 많이 기능을 제공한다. for와 while에 집착하지 말고 많은 것을 사용해보아야 한다.

직관적이고 쉬운 for-while은 쓰기가 좋지만 실제 효율은 매우 떨어진다. 그렇기 때문에 다른 것들 써보아야한다.





from functools import reduce

add5 = lambda n: n+5

reduce(lambda l, x:l+[add5(x)], range(10), [])

[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]


                                                                                         

컴프리헨션으로 만들면 더 쉽다.

[x+5 for x in range(10)]


for, while, recursion, iterator-generator, comp-higher-order functions



함수가 함수를 리턴하면 3가지 보자:

  1. 클로저

  2. 데코레이터

  3. 제너레이터

  

함수형 패러다임 암기... : 익숙해지는데 시간이 걸린다.






함수형 패러다임 때문에 연산도 연산자가 아니라 operator를 사용해서 하기도 한다.

import operator

operator.add(3, 4)
operator.sub(4, 3)





from functools import partial

x = partial(operator.add, 2)

x(3) : 5

x(4) : 6


클로저와 비슷한 형태로 돌아간다. partial(operator.add, 2)

t = [partial(operator.add,i) for i in range(1,11)]

t[0](10) : 11

------------------------------------------------------------------------------------------------------------------------



객체 지향 프로그래밍 : 파이썬에서 가장 중요하다. 그 동안 배운 파이썬 프로그래밍은 조금 당겨서 배운 것.


파이썬은 모든 것이 객체다. 순수한 객체. 함수형 패러다임은 100% 지원하지 않는다. 순수한 함수형 패러다임이 아니다.

하지만 순수한 객체지향언어다. 최고의 객체지향 언어. 파이썬



객체, 선언과 사용이 다르다. 함수처럼


함수 선언. 함수 호출. 클래스 선언. 인스턴스화. 실제 움직이는 애. 사용하는 애, 인스턴스.


class A:
  x = 3
  def y(self):
    self.t = 1
    
self.t : 인스턴스 변수, 인스턴스 어트리뷰트


ttt = A() : 이렇게 하면 인스턴스화라고 한다. ttt는 인스턴스, 객체


클래스는 결국 인스턴스화해서 사용해야한다.



리터럴 vs 객체(인스턴스화)

a = int()


vars(a) : 되는것도 있고 안되는 것도 있다.

a = [] : 리터럴

a = list() : []


파이썬은 기본적으로 오브젝트가 클래스 선언 뒤에 생략되어있다.

class X(object) : -> 기본적으로 오브젝트의 성질을 물려받게 된다.
  a = 3

클래스 변수... X.a 클래스 변수는 모든 인스턴스에 똑같다. 

클래스 하나 만들어두면 계속 재사용 가능하다.


t = X()

s = X()

c = X()

......

계에에에속 쓸 수 있음


객체지향에서는 t, s, c가 각각 다른 역할을 하도록 만드는 것이 의미가 있다.

위에 X()처럼 같은 역할을 한다면 아무런 의미가 없게 될 것이다.



정의할 때는 self를 쓰지만 사용할 때는 self없이 쓴다.


class X:
  a = 3
  def set_b(self, b):
    self.b = b
    
  t = X()
  t.set_b(3)
  t.b : 3
  
  s = X()
  s.set_b(4)
  s.b : 4
  

  
리터럴 방식은 내부적으로 클래스를 이용해서 만들어진다.


인스턴스화 하는 것이 기본이다.
  

self는 인스턴스가 가지는 애다. -> 인스턴스마다 다르게 가질 수 있는 값


s.a = 5 -> 이 s라는 인스턴스가 X를 사용해 만들었지만 이걸 5라고 바꾼다고 해서 X가 실제로 X.a가 5로 변하지는 않는다.
t.a : 3
X.a : 3 -> 클래스 변수다.


X.b : AttributeError -> 인스턴스 변수이기 때문에 클래스 이름으로는 사용할 수 없다.




vars(s)
{'a': 5, 'b': 4}



class X:
    a = 3
    def __init__(self, 5):
        self.a = 5
        
        
__init__이 생성자이다. 클래스를 생성할 때 먼저 만들게 된다.


class X:
    a = 3
    def __init__(self, b):
        self.a = b
        
초기값을 주어야 생성되는 변수가 a이다

s = X(4)


s.a = 4



class X:
    a = 3
    def __init__(self, b):
        self.a = b
    @classmethod
    def ttt(self):
        print(self.a)
        
        
@classmethod를 붙여주면 클래스를 이용해서 쓸 수 있다.
    
X.ttt() : 3
    
클래스 메소드를 붙이면 클래스 변수를 가져온다. (우선순위가 변경된다)


a = X(5)

a.ttt() : 3이다. 5가 아니다. classmethod이기 때문이다.


class X:
    a = 3
    n = 1
    def __init__(self, b,t):
        self.a = b
        self.n = t
#     @classmethod
    def ttt(self):
        print(self.a)
        print(self.n)
        
        
s = X(1,2)

vars(s) : {'a': 1, 'n': 2}
s.__dict__ : {'a': 1, 'n': 2}

__ : 이게 들어가는 순간 매직메소드, 스페셜메소드가 된다.


type(s) : __main__.X
s.__class__ : __main__.X


약간씩 다르다.

dir(s)와 s.__dir__()처럼 : dir(s)는 정렬이 되어있다.

매직메소드보다는 그냥 dir처럼 함수를 더 많이 사용한다.

Beautiful is better than ugly.


X.__module__ : '__main__'
int.__module__ : 'builtins'

클래스가 어느 모듈에 있는지를 알려준다.



연산자 오버로딩




OOP의 4가지 개념 : Abstraction, Encapsulation, Inheritance, Polymorphism




multiple-dispatch, single-dispatch overloading 지원