파이썬은 클래스를 지원하므로 객체 지향적인 프로그래밍을 할 수 있다. 사실 지금까지 다뤄온 기본 자료형도 다 클래스이다. 클래스는 새로운 자료형을 정의하는 것이고 객체(object)는 클래스의 인스턴스(instance, 클래스가 구체화된 것)를 의미한다.


클래스는 다음과 같이 정의한다.


class 식별자:
클래스 본체


보통 클래스의 식별자는 대문자로 시작한다. 예를 들어 Person, Robot, Car, Point 등이다. 클래스 본체는 이 클래스에 속하는 변수와 함수를 정의하게 된다. 특별히 클래스에 속한 변수들을 필드(field), 클래스에 속한 함수들을 일반 함수들과 구분하기 위해서 메소드(method)라고 부르며 이 둘을 통칭하여 속성(attribute)라고 한다.


이 용어들에 대해서는 숙지해 두는 것이 좋다.


  • 필드 (field) : 클래스에 내장된 변수

  • 메쏘드 (method) : 클래스에 속하는 함수

  • 속성 (attribute) : 필드와 메쏘드를 통칭하여 속성이라 한다.


가장 간단한 형태의 클래스를 다음과 같이 정의해 보자.


class Robot:
pass


이 클래스는 보면 알겠지만 본체가 없다. 이 클래스의 인스턴스를 생성하려면 다음과 같이 하면 된다.


>>> asimo = Robot()


이제 asimo 는 Robot 클래스의 객체가 되었다. 이와 같이 어떤 클래스의 객체(인스턴스)를 생성하려면 다음과 같이 한다.


변수명 = 클래스명()


마치 함수를 호출하는 것과 유사하다.



Posted by 살레시오
,

 다음은 기본 자료형의 생성과 변환에 관련된 내장 함수들이다.


[표 2] 기본 자료형의 생성과 변환에 관련된 내장 함수들

함수명

기능

object()

새로운 object (모든 객체의 base)를 생성한다.

bool(obj)

객체의 진리값을 반환한다.

int(obj)

문자열 형태의 숫자나 실수를 정수로 변환한다.

float(obj)

문자열 형태의 숫자나 정수를 실수로 변환한다.

complex(re [, img])

문자열이나 주어진 숫자로 복소수를 생성한다.

str(obj)

객체를 출력할 수 있는 문자열로 반환한다.

list(seq)

시퀀스형을 받아서 같은 순서의 리스트로 만들어 반환한다,

tuple(seq)

시퀀스형을 받아서 같은 순서의 튜플로 만들어 반환한다,

range(stop)

range(start,stop[,step])

0부터 stop-1 까지의 sequence 반환

start부터 stop-1 까지 (step은 간격) sequence 반환

set(seq)

시퀀스형을 받아서 같은 순서의 집합(set)으로 만들어 반환한다,

frozenlset()


bytes()


bytearray()


memoryview()


dict(**kwarg)

시퀀스형을 받아서 딕셔너리로 만들어 반환한다,

(음영진 부분은 seq 형이다.)


다음은 기본 자료형의 정보를 얻는 내장 함수들이다.


[표 2] 기본 자료형의 정보를 얻는 내장 함수들

함수명

기능

type(obj)

객체의 형을 반환한다.

dir(obj)

객체가 가진 함수와 변수들을 리스트 형태로 반환한다.

repr(obj)

ascii(obj)

evla()함수로 다시 객체를 복원할 수 있는 문자열 생성

repr()과 유사하나 non-ascii 문자는 escape한다.(?)

id(obj)

객체의 고유번호(int형)을 반환한다.

hash(obj)

객체의 해시값(int형)을 반환. (같은 값이면 해시도 같다.)

chr(num)

ord(str)

ASCII 값을 문자로 반환

한 문자의 ASCII 값을 반환

isinstance(obj, className)

객체가 클래스의 인스턴스인지를 판단한다.

issubclass(class, classinfo)

class가 classinfo 의  서브클래스일때 True 반환

classmethod()


staticmethod()


callable(obj)

obj가 호출 가능한 객체면 True반환 (ver 3.2에서 다시 도입)

getattr(obj, name)

setattr(obj,name,val)

delattr(obj,name)

hasattr(obj,nema)

obj의 attrubue (name) 를 얻는다.

obj의 attrubue (name) 를 설정한다.

obj의 attrubue (name) 를 삭제한다.



Posted by 살레시오
,

 파이썬의 내장 함수는 import 하지 않고 즉시 사용 가능한 함수들이다. 내장 함수명은 일종의 키워드로 간주하여야 하며 사용자의 식별자로 사용하는 것은 피하여야 한다.


 이하 표에서 대괄호 [ ..]로 표시된 것은 ‘생략 가능함’을 나타내는 것이다.


[표 1] 기본 입출력과 관련된 파이썬 내장 함수들

함수명

기능

print(x)

객체를 문자열로 표시한다.

input([prompt])

사용자 입력을 문자열로 반환한다.

help([x])

x에 대한 도움말을 출력한다.

globals()

전역 변수의 리스트를 반환한다.

locals() 혹은 vars()

vars(obj)

지역 변수의 리스트를 반환한다.

__dict__ 어트리뷰트를 반환한다. (객체의 내부 변수가 저장된 딕셔너리)

del(x) 혹은 del x

객체를 변수 공간에서 삭제한다.

eval(expr)

값을 구한다.

exec(obj)

파이썬 명령을 실행시킨다.

open(filename[,mode]))

파일을 연다


eval()함수는 파이썬 표현식을 실행해서 결과값을 얻는 함수이다.


>>> x = 1
>>> eval('x+1')
2


반면 exex()함수는 파이썬 프로그램 조각을 입력 받아서 파싱(parsing)한 후 실행시키는 함수이다. 파이썬 코드를 문자열로 넘겨줄 수도 있고 파일 객체를 넘겨줄 수도 있다.


>> a=10
>>> exec('b=a+10')
>>> b
20


open()함수는 존재하는 파일을 열거나 새로 파일을 생성하여 file객체를 반환해 주는 함수이다.


>>> f = open(‘test.txt’) # 존재하는 test.txt 파일을 연다.


위와 같이 mode 인자가 생략되면 읽기 모드인 ‘r’ 로 기본 설정된다. 모드는 다음과 같은 것이 있다.


[표 2] 내장함수 open()의 mode 옵션

mode

기능

‘r’

‘w’

‘x’

‘a’

읽기 모드로 연다 (기본값)

쓰기 모드로 연다. 기존 내용이 있다면 삭제됨

독점 모드로 파일을 생성한다. 기존 파일이 있다면 오류 발생

쓰기 모드로 연다. 기존 내용에 이어서 첨가하는 모드이다.

‘b’

‘t’

바이너리 모드(파일 내용이 bytes 객체로 반환됨)

텍스트모드(기본값, 파일 내용이 str 객체로 반환됨)

‘+’

내용을 갱신하기 위해서 파일을 연다.(읽기/쓰기)



Posted by 살레시오
,

 익명 함수(lambda function)란 말 그대로 이름이 없는 함수이며 파이썬에서는 lambda 라는 키워드로 익명 함수를 정의할 수 있다. 주로 비교적 간단한 기능의 함수가 컨테이너의 요소로 들어가는 경우 혹은 다른 함수의 인자로 함수를 넘겨줄 필요가 있을 때 사용된다.


익명 함수는 다음과 같이 생성된다.


lambda 인자1,인자2, … : 표현식


익명 함수는 보통 한 줄로 정의된다. return문도 없으며 단지 인자들과 반환값들의 관계식으로만 표현된다. 예를 들어 두 수의 합을 반환하는 익명 함수는 다음과 같다.


>>> add = lambda a, b : a+b
>>> add(1,2)
3


이 익명 함수는 다음과 같이 일반 함수를 정의하는 것과 동일하다.


>>> def add(a, b) :
…..      return a+b
>>> add(1,2)
3


그렇다면 일반 함수와 익명 함수와의 차이점은 무엇인가? 익명 함수의 기능은 일반 함수보다도 훨씬 제한적이고 익명 함수로 할 수 있는 것은 일반 함수로도 모두 할 수 있다. 그렇다면 왜 익명 함수를 사용할까?


때로는 굳이 번거롭게 일반 함수를 정의할 필요가 없는 간단한 기능만을 구현해도 되는 경우가 있다.  예를 들어서 입력 인수가 0보다 크면 True를 반환하는 함수를 생각해 보자.


>>> def pos(x):
…..    return x>0
>>> list(filter(pos, range(-5,6)))
[1,2,3,4,5]


이것을 익명 함수를 이용하면 다음과 같이 간단하게 처리할 수 있다.


>>> list( filter(lambda x:x>0, range(-5,6)) )
[1,2,3,4,5]


또는 다음과 같이 간단한 함수들을 리스트의 요소로 지정할 경우도 있을 것이다.


>>> fl = [lambda x,y:x+y, lambda x,y:x*y]
>>> fl[0](1,2)
3
>>> fl[1](3,4)
12


이와 같이 람다 함수의 용도는 보다 간결하게 원하는 기능을 수행할 수 있도록 하는 것이다.



Posted by 살레시오
,

 키워드 인자(keyword parameter)는 함수를 호출할 때 인자의 값 뿐만 아니라 그 이름까지 명시적으로 지정해서 전달하는 방법이다. 만약 기본 인자가 세 개인 다음과 같은 간단한 함수가 있다고 가정하자.


def add(a=0, b=0, c=0):
   return a+b+c


이 함수를 호출하는 방법은 다음과 같은 것들이 있다.


>>> add()
0
>>> add(11) # a에 11이 대입됨
11
>>> add(11,22) # a에 11, b에 22가 대입됨
33
>>> add(11,22,33) # a에 11, b에 22, c에 33이 대입됨
66


   ··············································································································

   ··············································································································


여기서 보듯이 인자의 순서대로 기본값 인자가 결정된다. a만, 혹은 a와 b에만 원하는 값을 대입하는 것은 문제가 없다. 그런데 만약 a와 b는 기본 인자 그대로 사용하고 c에만 다른 값을 넣어주고 싶을 때는 어떻게 해야 할까? 이런 경우 호출하는 쪽에서 변수명(키워드)를 지정하면 된다.


   ··············································································································

>> add(c=33) # c에만 33이 대입된다.

>> add(c=33, b=22) #c에 33, b에 22가 대입된다.

   ··············································································································


이와 같이 키워드 인자값을 넘겨줄 때에는 함수 정의부의 인자 순서와 상관 없이 나열할 수 있다.

기본값 인자와 마찬가지로 키워드 인자는 함수 정의시에 일반 인자(standard argument) 뒤에 와야 한다.


def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
   print("-- This parrot wouldn't", action)
   print("if you put", voltage, "volts through it.")
   print("-- Lovely plumage, the", type)
   print("-- It's", state, "!")


이 함수는 일반 인자(voltage) 하나와 세 개의 기본 인자(state, action, type)을 가지고 있다. 이 함수는 다음과 같이 호출될 수 있다.


parrot(1000)
parrot(voltage=1000)
parrot(voltage=1000000, action='VOOOOOM')
parrot(action='VOOOOOM', voltage=1000000)
parrot('a million', 'bereft of life', 'jump')
parrot('a thousand', state='pushing up the daisies')


하지만 다음과 같이 호출할 수는 없다.


parrot()                     # 일반 인자값 없음
parrot(voltage=5.0, 'dead')  #키워드 인자 뒤에 일반 인자값을 주지 못함
parrot(110, voltage=220)     # 한 인자에 두 값을 주지 못함
parrot(actor='John Cleese')  # actor라는 키워드가 없음


함수 호출할 때에도 키워드 인자는 일반 인자 뒤에 와야 한다. 또한 키워드 인자로 넘겨지는 것은 반드시 함수 정의에서 매칭되는 변수가 있어야 하며 호출하는 순서는 중요하지 않다.


만약 함수 정의부에 **kwargs 와 같은 형태의 인자가 있다면 kwargs는 딕셔너리 형태로 키워드 인자들 중에서 일반 인자가 아닌 것들을 넘겨 받는다. 만약 가변 개수 인자 *args 와 혼용하는 경우에는 반드시 이것 뒤에 와야 한다.


def f(a, *args, **kwargs):
   print('a=',a)
   print('args=',args)
   print('kwargs=',kwargs)


이 함수는 다음과 같이 호출될 수 있다.


>>> f(11)
a= 11
args= ()
kwargs= {}
>>> f(11,22,33)
a= 11
args= (22, 33)
kwargs= {}
>>> f(11,22,33,b=44,c=55)
a= 11
args= (22, 33)
kwargs= {'c': 55, 'b': 44}


이 예에서 보듯이 반드시 일반 인자(a), 가변 개수 인자(*args), 키워드 인자(**kwarg) 의 순으로 나열되어야 함을 주의하자.



Posted by 살레시오
,

 파이썬 함수의 기본값 인자(default parameter)란 함수를 호출할 때 인자의 값을 설정하지 않아도 기본값이 할당되도록 하는 기능이다. 기본값은 함수를 정의할 때 지정해준다. 예를 들어 보자.


def funcA(a=10):
   print('a='+str(a))


이 함수는 다음과 같이 두 가지 방법으로 호출할 수 있다.


>>> funcA() # a에 기본값인 10이 자동으로 저장된다.
a=10
>>> funcA(20) #a에 20이 전달된다.
a=20


이 예에서 인자 a는 기본값 인자이고 호출하는 쪽에서 값을 주지 않으면 기본적으로 10 값을 갖게 된다. 그래서 funcA()와 같이 값을 주지 않으면 10이 출력되고 funcA(20)과 같이 값을 주면 그 값이 인자 a 로 전달되는 것이다.


 다른 예를 들어 보자.


def printName(firstName, secondName='Kim'):
   print('My name is '+ firstName +' ' + secondName +'.')


이 함수도 다음과 같이 두 가지 방법으로 호출 가능하다.


>>> printName('Jang-Hyun')
My name is Jang-Hyun Kim.
>>> printName('Jang-Hyun', 'Park')
My name is Jang-Hyun Park.


기본값 인자는 값을 생략해서 호출할 수 있지만 일반 인자는 반드시 값을 지정해 주어야 한다. 따라서 printName()함수를 호출할 때 첫 문자열은 반드시 정해서 넘겨주어야 한다. 여기에서 printName()함수의 두 번째 인자를 입력하지 않으면 기본적으로 ‘Kim’으로 지정된다. 두 번째 인자를 명시적으로 지정하면 그것이 secondName 으로 지정된다.


 한 가지 주의할 점은 일반 인자와 기본값 인자가 같이 올 때에는 반드시 기본값 인자는 뒤에 와야 한다는 점이다. 즉, 아래와 같이 정의하면 오류가 발생한다.


>>> def printName(firstName='Kim', secondName):


기본값 인자가 두 개 이상일 때에서도 항상 일반 인자 뒤에 와야 한다.


>>> def add(a, b=0, c=0):
...     return a+b+c
...
>>> add(1)
1
>>> add(1,2) # b에 2가 들어간다.
3
>>> add(1,2,3) # b에 2, c에 3이 들어간다.)
6


이 예에서 보듯이 함수를 호출할 때 주는 순서 대로 기본값 인자에 값이 할당 됨을 알 수 있다.


 또 한 가지 주의할 점은 기본 인자는 최초의 호출 시에만 지정된 값으로 초기화 되고 이후의 호출에서는 그렇지 않다는 점이다. 따라서 리스트나 딕셔너리와 같은 가변(muatble) 객체를 기본 인자로 사용할 때 문제가 된다.


>>> def f(a, L=[]):
...     L.append(a)
...     return L
...
>>> f(1)
[1]
>>> f(2)
[1, 2]
>>> f(3)
[1, 2, 3]


이 예제를 보면 기본 인자 L은 최초의 호출에서만 빈 리스트로 초기화 되고 그 이후의 호출에서는 그 내용물은 유지된다. 따라서 리스트의 요소가 축적되는 것이다. (마치 C/C++에서의 static 변수와 비슷한 동작을 수행한다.)


 후속 호출에도 mutalbe 객체를 초기화하려면 다음과 같은 방법으로 코딩하면 된다.


def f(a, L=None):
   if L is None:
       L = []
   L.append(a)
   return L


이 경우 실행 결과는 다음과 같다.


>>> f(1)
[1]
>>> f(2)
[2]
>>> f(3)
[3]




Posted by 살레시오
,

 어떤 함수는 호출하는 쪽에선 몇 개의 인수를 넘겨줄지 모르는 경우가 있다. 이럴 경우에 사용되는 것이 가변 개수 인자 기능으로써 함수는 넘어온 인자들을 묶어서 단일 튜플로 받는다.


 예를 들어 입력 인자들 중 짝수의 개수를 구하는 함수를 작성해야 하는데 몇 개의 입력이 들어올 지는 모른다고 가정하자. 인자들을 묶어서 한 개의 리스트를 받는 방식을 먼저 생각해 볼 수 있겠다.


def count_even(lst):
   cnt = 0
   for v in lst:
       if v%2==0:
           cnt +=1
   return cnt

>>> count_even([1,2,3,4,5,6,7])
3
>>> count_even([11,22,33])
1


이런 식으로 하나의 입력 인수를 받되 리스트 요소의 개수는 그때 그때 변할 수 있겠다.


 하지만 이런 경우에 있어서 좀 더 일반적인 해법은 가변 개수 인수를 받는 것이다. 가변 개수 인자를 지정할 때 함수의 정의부에서 변수 앞에 별표(*)를 붙인다.


>>> def count_even(*n):
   cnt = 0
   for v in n:
       if v%2==0:
           cnt +=1
   return cnt

>>> count_even(11,22,33)
1
>>> count_even(1,2,3,4,5,6,7)
3


앞의 경우와 다르게 함수를 호출할 때 콤마로 구분된 입력 인자를 몇 개라도 입력할 수 있다는 것이다. 함수 내부에서는 이들 인자들을 요소로 갖는 튜플이 변수 n에 넘어오게 된다. 즉 type(n)은 tuple 이다.


 한 가지 주의할 점은 일반 인자와 가변 인자가 동시에 오는 경우 반드시 가변 인자는 일반 인자 뒤에 와야 한다는 점이다. 또한 가변 인자는 단 하나만 사용할 수 있다는 것도 유의해야 한다.


>>> def  f1(a, *b): # 정상
>>> def  f2(a, *b, c): # 오류 - 가변 인자 뒤에 일반 인자가 올 수 없다.
>>> def  f3(*a, *b): #오류 - 가변 인자는 하나만 사용 가능
>>> def  f4(a, b, *c) # 정상


이러한 사항에 주의해서 함수를 작성해야 한다.




Posted by 살레시오
,

 함수에는 입력 인자(argument)가 있을 수도 있고 없을 수도 있으며 반환값도 마찬가지이다. 호출하는 쪽에 반환값을 되돌려주기 위해선 return 이라는 키워드를 이용하여 그 뒤에 반환할 값을 써 주면 된다.


>>> def sayHi():
   print('Hi.')
>>>a = sayHi()
Hi.


여기에서는 반환값이 없는 함수의 결과값을 a변수에 저장하였는데 (일반적이지 않은 방법이긴 하지만) 오류를 발생하지 않는다. 이 경우 a라는 변수에 None 값이 저장된다.


>>> type(a)

NoneType


 함수를 호출하는 쪽에서는 순서대로 값을 입력해야 한다.


>>> def mod(x,y):
….. return x%y
>> mod(3,2) # x에 3, y에 2가 전달된다.


이 예는 x를 y로 나눈 나머지를 반환하는 함수인데 입력 인수는 순서대로 정의된 모든 변수에 주어야 한다. 다음과 같은 호출은 오류를 발생시킨다.


>>> mod()
>>> mod(3)
>>> mod(3,2,1)


이와 같이 함수의 정의부에 변수명만 있는 인자를 일반 인자(standard argument)라고 하며, 호출하는 쪽에서는 반드시 순서와 개수를 맞추어서 넘겨주어야 한다.


 반환 값이 두 개 이상일 경우에는 return 명령 뒤에 콤마(,)로 구분해야 한다.


>>> def cal(x,y):
...     return x+y, x-y         
...

>>> cal(11,22)  # 반환값은 튜플이다.
(33, -11)

>>> a,b=cal(33,44)
>>> a
77
>>> b
-11


이 간단한 예제에서 cal() 함수는 두 수의 합과 차 두 개를 반환한다. 호출하는 쪽에서는 결과 값들의 튜플을 받게 된다. 다른 변수로 각각 받으려면 위와 같이 하면 된다.


>>> a, b = cal(33,44)


a변수에는 합이, b변수에는 차가 저장됨을 알 수 있다.



Posted by 살레시오
,

 함수(function)란 실행문들을 묶어서 하나의 블럭으로 만든 후 이름을 붙인 것을 말한다. 이렇게 수행문들의 집합을 함수로 정의하면 그 수행문들을 동작시킬 때 함수 이름을 이용한 간단한 호출(call)로 반복해서 실행시킬 수 있다.


 파이썬 함수는 다음과 같이 정의된다.


def 함수명(인자1, 인자2, …):
함수 본체


함수의 정의는 항상 def로 시작한다. 함수명은 일반적인 식별자를 사용하며 관례적으로 (변수명과 마찬가지로) 소문자로 시작한다. 그다음에 호출하는 쪽에서 넘겨 받을 인자들의 리스트를 괄호(...)안에 콤마로 구별하여 지정해 주고 콜론(:) 뒤에 함수의 본체를 작성해 주면 된다. 함수의 본체는 반드시 def 의 첫 글자 시작 위치보다 들여 써야 한다.


 간단한 예를 들어보자


>>> def sayHi():
print(‘hi’)


이 함수는 ‘hi’라는 문자열을 출력하는 함수이며 함수의 이름은 sayHi()이다. 입력 인자는 없으며 반환값도 없다. 이 함수를 호출하려면 다음과 같이 하면 된다.


>>> sayHi()
Hi


구구단을 출력하는 함수를 예로 들어보자.


>>> def gugu(n):
...     for x in range(2,10):
...         print('%d x %d = %d'%(n,x,n*x))


이 함수는 하나의 입력 인자를 받도록 되어 있다. 다음과 같이 호출한다.


>>> gugu(4)
4 x 2 = 8
4 x 3 = 12
4 x 4 = 16
4 x 5 = 20
4 x 6 = 24
4 x 7 = 28
4 x 8 = 32
4 x 9 = 36

>>> gugu(8)
8 x 2 = 16
8 x 3 = 24
8 x 4 = 32
8 x 5 = 40
8 x 6 = 48
8 x 7 = 56
8 x 8 = 64
8 x 9 = 72


함수명은 함수객체이며 다른 객체와 유사하게 대입이 가능하다. 예를 들어 앞에서 정의한 함수 sayHi()와 gugu()를 하나의 리스트로 묶을 수 있다.


>>> fl = [sayHi, gugu]


여기서 fl 리스트의 첫 번째 요소는 함수 sayHi 이고 두 번째 요소는 gugu 이다. 따라서 다음과 같은 함수 호출이 가능하다.


>>> fl[0]()
Hi.
>>> fl[1](9)
9 x 2 = 18
9 x 3 = 27
9 x 4 = 36
9 x 5 = 45
9 x 6 = 54
9 x 7 = 63
9 x 8 = 72
9 x 9 = 81



또는 함수를 다른 변수에 대입할 수도 있다.


>>> kuku = gugu


이제 kuku 는 함수이며 gugu()함수와 같은 함수이다. 따라서 다음과 같이 동일하게 호출할 수도 있다.


>>> kuku(7)
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63


 가끔 함수의 본체를 구현하지 않고 껍데기만 작성해야 될 경우도 있다. 이럴 경우 다음과 같이 하면 된다.


>>> def nop(): pass


이 함수는 호출은 할 수 있으나 아무런 일도 수행하지 않는다.



Posted by 살레시오
,

 반복문 안에서 continue 명령은 그 이후의 반복문은 수행하지 않고 즉시로 다음 반복 실행으로 넘어가는 동작을 수행한다.


for n in lst:
   if n==0:
       continue
   print(n)


이 예제에서 lst의 요소가 만약 0 이라면 continue 명령을 만나게 되고 그 이후의 print(n)은 수행되지 않고 다음으로 바로 넘어가게 된다.


 이 예를 while 문으로 작성하면 다음과 같다.


k = 0
while k<len(lst) :
   if lst[k]==0:
       k +=1
       continue
   print(lst[k])
   k +=1


이와 같이 continue 명령은 반복문 안에서 사용되며 그것을 둘러싼 가장 안쪽의 반복문의 다음 단계로 즉시 넘어가는 동작을 수행한다.



Posted by 살레시오
,