1. iter 함수

- 우리는 보통 하나 이상의 값을 저장하거나 저장된 값들을 하나씩 꺼내 볼 때, for 루프를 이용함 

 - ds에 저장된 것 하나씩 꺼내서 출력하는 for 루프 

 

 - iter라는 함수를 호출하면서 리스트를 전달했음

 - iter함수는 객체를 생성해서 반환 = 리스트에서 값을 꺼내는 기능을 제공 



 

 - ir = iter(ds) : 리스트 ds를 전달하면서 iter 함수를 호출하였음

 

 - 이미 마지막 값을 얻었음에도 불구하고 다시 next 함수를 호출하면 위와 같이 예외가 발생함

 

- 마지막 값을 얻고 다시 처음부터 값을 얻으려면 iterator 객체를 다시 불러오면 됨 

- 이런 방식으로 값을 꺼내게 되면, 원하는 시기에 하나씩 값을 꺼낼 수 있음 

- 사탕으로 예를 들자면, 하루에 모든 사탕을 다 꺼내 먹을 수 있지만, 마지막 사탕은 남겨뒀다가 내일 먹을수도 있음

- 즉, 꺼내는 방법과 꺼낸 값을 처리하는 방법에 있어서도 유연성이 생김





2. Iterable 객체와 Iterator 객체의 구분 

Iterable 객체 - iter 함수에 인자로 전달 가능한 객체
- iterator 객체를 얻을 수 있는 리스트와 같은 객체
Iterator 객체 - iter 함수가 생성해서 반환하는 객체

 

- 어떤 객체가 iterator/iterable 객체인지 확인하는 방법 = iter 함수에 전달해 보는 것 

- 전달 결과로 오류 없이 iterator 객체가 만들어진다면, 이것은 iterable 객체인 것 

 

 🡺 iterable 객체를 대상으로 iter 함수를 호출해서 iterator 객체를 만듦

 🡺 iterator 객체를 생성할 수 있는 대상이 되는 것이 iterable 객체임 



3. 스페셜 메소드

- 위와 같은 방식으로 작성하면, iter 함수와 next 함수는 객체에 속하지 않는 함수처럼 보임

- 그러나 실제 함수 호출 형태는 아래와 같음

>>> ds = [1, 2, 3]
>>> ir = ds.__ite.r__( )
>>> ir.__next__( )
1
>>> ir.__next__( )
2

🡺 리스트의 __iter__ 메소드 호출을 통해서 iterator 객체를 얻게 됨 

 🡺 iterator 객체의 __next__ 메소드 호출을 통해서 값을 하나 씩 얻게 됨 

 

 - 이렇게 직접 호출하지 않아도 파이썬 인터프리터에 의해서 호출되는 메소드를 ‘스페셜 메소드(special method)라고 부름 

     : 객체 생성 시 자동으로 호출되는 __init__ 메소드도 스페셜 메소드임 

 

4. Iterable 객체의 종류와 확인 방법

 - 튜플로도 iterator 객체를 얻을 수 있음

 

 - 문자열을 대상으로도 iterator 객체를 얻을 수 있음 

 - dir 함수를 호출해서 __iter__ 메소드가 존재하는지 확인하는 방법으로도 iterable 객체인지 아닌지 판단할 수 있음 

 

 - 리스트에 __iter__함수가 있는지 묻는 것으로도 판단할 수 있음

 

5. for 루프와 Iterable 객체

 - for 루프도 값을 하나씩 꺼내기 위해 iterable 객체를 생성해서 도움을 받음 

 

 - iterator 객체를 얻음 

 - iterator 객체를 통해서 값을 하나씩 꺼낸 뒤, 더 이상 꺼낼 것이 없으면 루프를 탈출하도록 함 

 

 - 따라서, for 루프의 반복 대상은 반드시 iterable 객체여야만 함 

 - iter 함수의 인자로 전달이 가능한 iterable 객체여야 함 

 - 그래서 iterable 객체인 리스트, 튜플, 문자열은 for 루프의 반복 대상이 될 수 있는 것 

 

 - ir에 저장되는 것은 iterator 객체 

 - for 루프에 iterator 객체를 가져다 두었음

 - 이처럼, for 루프에 iterable 객체가 아닌 iterator 객체를 두어도 정상적으로 작동함 

 

 - 그 이유는 위와 같이 iter 함수에 iterator 객체를 전달하면 전달된 iterator 객체를 그대로 되돌려주기 때문임

 

 🡺 iterable 객체와 iterator 객체 모두 for 루프의 반복 대상이 될 수 있다. 

 🡺 iterable 객체가 와야 하는 위치에는 iterator 객체가 올 수 있다. 

 

1. 두 객체의 비교와 복사

 - 객체를 비교할 때 사용할 수 있는 두 가지 연산자

v1 == v2 변수 v1v2가 참조하는 객체의 내용이 같은가?
v1 is v2 변수 v1v2가 참조하는 객체는 동일 객체인가?

 

 - r1 is r2 : r1r2가 참조하는 객체는 같은 객체인가?

 - r1 == r2 : r1r2가 참조하는 객체에 담긴 값은 같은가?

 

- is 연산이 True를 반환하는 상황

 - r2 = r1 : r1이 참조하는 리스트에 r2라는 이름을 하나 붙임

 

- r1 = [‘Arin’, (‘woman’ ‘Korea’), [162, 22]]

- 리스트를 생성하면 리스트 안에 선언되는 값들이 리스트에 들어가 있는 형태가 아니라 각 값들(객체들)을 리스트 내에서 참조하는 형태가 됨

 

- r2 = list(r1)

 : list 함수를 호출하면서 리스트를 전달하였음

     : 전달된 리스트의 내용이 담긴 새로운 리스트가 만들어짐

 ☞ 이러한 형태의 복사를 얕은 복사라고 함

 

 - 얕은 복사

    : 파이썬이 복사를 진행하는 기본적인 방식

    : 값이 변경되지 않는 immutable 함수 (ex. 튜플, 문자열)를 사용하는데 적합함!

 

 

문자열 객체 ‘Arin’
튜플 객체 (‘woman’, ‘Korea’)

 

 - 리스트와 같이 내용을 수정할 수 있는 함수를 얕은 복사하면 문제가 생길 수 있음

 

2. 깊은 복사

 - mutable 함수를 얕은 복사를 하면 생기는 문제 예시

 - 2021Arin의 나이를 22살로 설정

 - 2021년의 Arin의 리스트를 2022년으로 복사한 뒤, 2022, 즉 일 년이 지났을 때 한살이 추가되도록 설정

 - 2021년의 Arin의 정보 : 한 살 더 추가되었음

 - 2022년의 Arin의 정보 : 한 살 더 추가되었음

 

 - , 얕은 복사로 인해 mutable 객체에 저장된 값이 변경될 수 있음

 - 따라서 immutable 함수는 얕은 복사로, mutable 함수는 copy 모듈의 deepcopy를 사용하여 깊은 복사를 해야 함

-  deepcopy를 위해서 copy 함수를 불러옴

- 얕은 복사와 깊은 복사를 확인했음

1. 파이썬에서는 함수도 객체

 - 실수는 float형 클래스의 객체임을 확인해라

 - x.is_integer() : 소수점 이하에 값이 있는지 묻는 메소드 호출

 - 변수 x를 대상으로 is_integer 메소드를 호출하고 있는데, 이는 x에 담긴 실수 3.0이 객체라는 증거가 됨

 - 그런데, 파이썬은 함수도 객체로 처리함

 - 즉 함수 = 객체

 

 - def func1(n) : 매개 변수가 있고 값을 반환하는 함수

 - def func2(n) : 매개변수 없고 값의 반환도 없는 함수

 - func1function 클래스의 객체임을 확인함

 - func2function 클래스의 객체임을 확인함

 

 - , 함수는 매개변수의 유무, 하는 일, 반환 값의 유무에 상관없이 모두 function이라는 클래스의 객체임

 - 우리가 함수를 정의하면, 파이썬은 그 함수의 내용을 기반으로 function 클래스의 객체를 생성하는 것

 

 - say1say2 함수를 caller에 전달하 ㄴ것

 - 함수도 객체라는 사실이 의미하는 바 è 먼저 매개변수에 함수를 전달할 수 있음

 

 - def exp(x) : 함수 내에서 정의된, xn제곱을 반환하는 함수

 - return exp : 위에서 정의한 함수 exp를 반환함

 - f2는 제곱을 계산해서 반환하는 함수를 참조함

 - f3는 세제곱을 계산해서 반환하는 함수를 참조함

1. 제너레이터에 대한 이해와 제너레이터 함수

 

 1) 제너레이터 함수(generators) 

   - iterator 객체의 한 종류 

   - 따라서 제너레이터를 전달하면서 next 함수를 호출하면 값을 하나 씩 얻을 수 있음

  

  ① 제너레이터 함수(function) : 제너레이터를 만들기 위한 함수 정의

  ② 제너레이터 표현식(expression) : 제너레이터를 만들기 위한 식

 

 - def gen_num( ) : 제너레이터 함수 정의

 - yield : yield가 하나라도 들어가면 제너레이터가 됨

 - gen = gen_num() : 제너레이터 객체 생성

 - 만약 gen = gen_num 함수가 일반 함수라면 위에 지정한 모든 내용들이 실행되는데, 제너레이터 객체로 만들어져서 반환된 것이기 때문에 모든 내용이 실행되지 않는다. 

 

 

 2) yield의 의미 

   - yield 1 : 첫 번째 next 호출에서 이 문장까지 실행됨

   - yield 2 : 두 번째 next 호출에서 이 문장까지 실행됨

   - yield 3 : 세 번째 next 호출에서 이 문장까지 실행됨 

 

 - 첫 번째 next 함수 호출

 

 - 두 번째 next 함수 호출

 

 - 세 번째 next 함수 호출

 

 

 3) 다 실행됐음에도 불구하고 다시 next 함수를 호출할 경우 

   - StopIteration 예외 발생

   - generation 객체 역시 iterator 객체이기 때문에 다음과 같은 예외문이 뜨는 것 

   - 함수 호출 이후에 그 실행의 흐름을 next 함수가 호출될 때 까지 미루는 특성을 'lazy evaluation'이라고 함  

 

 

2. 제너레이터가 갖는 장점

 - 제너레이터가 갖는 의미와 장점에 대해 살펴보겠음

 - 위 예제에서는 pows 함수 호출을 통해 [1, 2, 3, 4, 5, 6, 7, 8, 9] 이 배열을 기반으로  [1, 4, 9, 16, 25, 36, 49, 64, 81] 이 배열의 값을 하나씩 출력한 것 

 - 이 때 사용한 메모리 공간의 크기는 위와 같음 

 - 즉 st에 담긴 객체가 184바이트를 사용하고 있음

 

 - 이제 제너레이터를 기반으로 같은 예제를 작성하겠음

 - 이때의 메모리 공간이 적어진 것을 알 수 있음 

 - 별 차이는 없어 보여도, 메모리 공간의 크기는 리스트의 길이에 비례하지만, 제너레이터를 사용하는 위의 경우에는 리스트의 길이에 상관없이 사용하는 메모리 공간의 크기가 동일함

 - 그 이유는 제너레이터 객체는 반환할 값들을 미리 만들어서 저장해두지 않기 때문임 

 - 일전에 배운 map과 filter도 제너레이터 함수 

 

 

3. yield from

 - 제너레이터 함수 관련 파이썬 3.3 이상에서 사용할 수 있는 문법 

 - 0과 1을 순서대로 던져주는(반환하는) 제너레이터 

 

- for i in ns:

       yield i 

   : 리스트에 있는 값을 하나씩 yield 문을 통해서 전달하기 위한 for 루프

 

- yield from ns : ns에 있는 값들을 하나씩 yield문을 통해서 전달하겠음

- 위와 같이 단순하게 쓸 수 있는 것 

 

1. map과 filter를 대신하는 리스트 컴프리헨션

 - 리스트 컴프리헨션을 이용하면 확실히 map이나 filter 함수의 사용 빈도가 줄어듦

 - 그러나 map과 filter는 다양한 이유로 자주 사용되는 함수이므로 잘 알고 있어야 함 

 

 - map을 사용하는 예제 (제곱의 결과를 리스트로 묶기)

 

- 리스트 컴프리헨션을 사용한 예제 (제곱의 결과를 리스트로 묶기)

 

- filter 함수를 사용한 예제 (홀수만 남겨서 리스트로 묶기)

 

 

- 컴프리헨션 기반으로 작성한 예제 (홀수만 남겨서 리스트로 묶기)

 

- 1~10의 자연수 중에서 홀수들을 대상으로 제곱 값을 리스트에 담는 예제

 

- 리스트 컴프리헨션 기반으로 대체한 예제

- 매우 간결한 것을 알 수 있음 

 

1. map

- 위에서 정의한 pow 함수와 st1이 참조하는 리스트를 이용해서 

   st2 = [1, 4, 9]를 만들려고 한다. 

- st1의 값들을 pow 함수에 넣어서 반환된 값들로 이뤄진 리스트이다. 

- 어떻게 만들 수 있을까?

 

- 값을 일일이 넣어서 pow 함수를 호출함

- 그러나 매우 불편한 코드 

 

- map은 st1의 값들을 전달하면서 pow 호출함 

- 즉, st1에 저장된 값의 수 만큼 pow 함수가 호출되며, 그것이 pow 함수가 하는 일 

- 단 이 때 map의 두 번째 전달 대상은 literable 객체여야만 함 

 

- map 함수가 하는 일

- ir은 iterator 객체이므로 for 루프에 올 수 있음 

- iterable 객체라면 무엇이든 전달 가능함 

 

-  st1과 st2에 있는 값들을 각각 더해서 다음 형태의 리스트를 만들고자 할 때

    [4, 4, 4]

- 원래라면 리스트를 각각 지정해주고 return n1 + n2 함수를 써야 함 

 

 

2. map과 람다

 - 일반적인 슬라이싱 연산

- st[ : ] : 처음부터 끝까지 모든 값을 꺼내서 리스트 생성

- st[ : :1] : 처음부터 끝까지 한 칸씩 뛰면서 값을 꺼내 리스트 생성

- st[ : :2] : 처음부터 끝까지 두 칸씩 뛰면서 값을 꺼내 리스트 생성

- st[ : :3] : 처음부터 끝까지 세 칸씩 뛰면서 값을 꺼내 리스트 생성 

 

- 그런데, 이 사실은 책에서 배운 적이 없음

 " 슬라이싱 연산에서 세 번째 값이 음수이면 값을 꺼내는 방향이 달라진다. "

 

 - 세 번째 값이 음수이면 저장 순서를 뒤집은 결과를 만들 수 있음

 

 - 슬라이싱 연산을 문자열을 뒤집는데도 사용할 수 있음

 

 - 이렇게 map을 통해 rev 함수를 정의하는 경우, 람다를 사용하면 더 간결하게 표현할 수 있음

 - 이처럼 람다 함수를 사용하면 별도의 함수를 정의하지 않아도 됨

 

 

3. filter 

 - filter 함수

     : map과 마찬가지로 함수를 인자로 전달받음 

     : 이 함수는 값을 걸러내는 기준이 됨

     : 즉, filter 함수는 값을 걸러내는 기능을 제공하는 함수 

 - ost = list(filter(is_odd, st)) : is_odd를 기준으로 st에 저장된 값들 중 일부 걸러 냄 

 - 위의 문장에서 알 수 있듯이, filter 함수의 첫 번째 인자는 True 또는 False를 반환하는 함수여야 함

 - 두 번째 인자는 리스트나 튜플과 같이 값을 저장하고 있는 iterable 객체여야 함 

 

 - 작용 기작

  ① filter는 st에 저장된 값들을 하나씩 꺼내서 is_odd에 전달함

  ② is_odd가 True를 반환하는 값들만 따로 모음 

  ③ 이 값들을 얻을 수 있는 iterator 객체를 반환함 

 

 

 

 - 10 이하의 자연수 중에서 3의 배수만 리스트에 담는 예제 

 - range 객체도 iterable 객체이므로 filter의 두 번째 인자가 될 수 있음 

 

 - 1~10의 제곱을 리스트에 담되 3의 배수만 담은 예제

 - 1 ~ 10의 제곱을 만들기 위해서 map이 사용됨

 - 이 중에서 3의 배수만을 담기 위해 filter가 사용됨 

 

 - map(lambda n: n**2, st))) : map 함수를 호출하는 부분이 먼저 진행됨 

 - 이를 통해 리스트 st에 저장된 값들의 제곱해 해당하는 값들이 만들어짐

      : [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

 - 위의 값들을 하나씩 얻을 수 있는 iterator 객체가 반환되어 다음의 filter 함수 호출이 진행됨

      : map이 반환한 iterator 객체를 아래에서 ir1이라 함 

      : fst = list(filter(lambda n: not(n % 3), ir1))

 - 위의 filter 함수를 통해서 3의 배수만 통과되어 9, 36, 81만 남게 됨 

 - 위의 값들을 하나씩 얻을 수 있는 iterator 객체가 filter 함수 호출의 결과로 반환됨

      : filter가 반환한 iterator 객체를 아래에서 ir2이라 함 

      : fst = list(ir2)

 - 결국 9, 36, 81로 이뤄진 리스트가 생성되어 변수 fst에 저장됨 

 

 

[7-1. 참과 거짓을 의미하는 값(데이터)]

- True : 참을 뜻함, 질문 내용이 맞는 경우의 대답이 되기도 한다.

- False : 거짓을 의미함, 질문 내용이 맞지 않는 경우의 대답이 되기도 한다. 

 

- 3 > 10 : 3이 10보다 큰가?

- 3 < 10 : 3이 10보다 작은가?

 

- 파이썬은 True, False를 값으로 취급함 

 

int형 데이터 3, 5, 7, 9
float형 데이터 2.2, 4.4, 6.6, 8.8
리스트형 데이터 [3, 5, 7, 9], [2.2, 4.4, 6.6, 8.8]
스트링형 데이터 "I'm a boy", "You are a girl"
부울형 데이터 True, False

 

 

[7-2. 소스파일에 main 함수 만들기]

- 연산자의 기능이나 함수 호출의 결과 정도는 프롬프트상에서 확인하는 것이 편함

- 그러나 코드가 길어지면 이것이 불편하기 때문에, 코드를 채워 넣는 방식으로 학습

- 위의 코드를 소스파일에 담아서 실행하면 main함수가 먼저 정의되고, 이어서 main함수의 호출이 진행됨

 

 

[7-3. if문 : 조건이 맞으면 실행을 해라.]

- 특정 조건이 True인 경우에만 실행함

 

If <조건> :
    <if에 속하는 문장 1>
    <if에 속하는 문장 2>
    . . . .

 

 

- 화살표는 실행의 흐름을 의미함

- 동그란 조건 : 흐름의 분기(나뉨), 즉 조건이 True이면 사각형 안에 있는 if의 문자들이 실행되고, 조건이 False면 이를 건너뛰게 됨

 

 

 

[7-4. if ~ else문 : 이쪽 길! 아니면 저쪽 길!]

 - if ~ else문은 <조건>True가 오는 경우에 실행할 코드와 False가 오는 경우에 실행할 코드를 구분해야 할 때 사용하는 문장

if <조건> :
    <True시 실행할 문장들>
else :
    <False시 실행할 문장들>
 

 

 

[7-5. if ~ elif ~ else문 : 여러 길 중에서 하나의 길만 선택!]

 - if ~ else: 조건에 따라 둘 중 하나를 선택해서 실행하는 경우

 - if ~ elif ~ else: 조건에 따라 셋 또는 그 이상 중에서 하나를 선택하여 실행하는 경우

if <조건 1> :
    <조건 1True인 경우 실행할 문장들>
elif <조건 2> :
    <조건 2True인 경우 실행할 문장들>
else:
    <모든 조건 False인 경우 실행할 문장들>
 

 

 

[7-6. True 또는 False를 반환하는 연산들]

 

1) True, False 연산

A > Z : AZ보다 크면 True, 크지 않으면 False 반환
A < Z : AZ보다 작으면 True, 작지 않으면 False 반환
A >= Z : AZ보다 크거나 같으면 True, 그렇지 않으면 False 반환
A <= Z : AZ보다 작거나 같으면 True, 그렇지 않으면 False 반환
A == Z : AZ가 같으면 True, 같지 않으면 False 반환
A != Z : AZ가 같지 않으면 True, 같으면 False 반환

 

2) and 연산

A and Z : AZ가 모두 True이면 True, 그렇지 않으면 False 반환
A or Z : AZ 둘 중 하나라도 True이면 True, 그렇지 않으면 False 반환
not A : ATrue이면 False, A False이면 True 반환

 

- True, False : , and : 연산자

- True and True : 모두 True를 만족하므로 결과값은 True

 

- True, False : , or : 연산자  

- True or False : 둘 중 하나가 True이므로 True (왼쪽에 오든 오른쪽에 오든 상관 없음)

- False or False : 어느 쪽도 True가 없으므로 False

 

- True, False : , not : 연산자

- True가 아니므로 False, False가 아니므로 True

 

3) and 연산 결과 정리 

P1 P1 P1 and p2
True True True
True False False
False True False
False False False

 

4) or 연산 결과 정리 

P1 P1 P1 and p2
True True True
True False True
False True True
False False False

 

5) not 연산 결과 정리

P Not p
True True
False False

- 이러한 연사자를 사용하는 방법 : TrueFalse를 반환하는 연산으로 가져다 놓기

 

 <연습문제 07-1>

▶ 문제 1. 프로그램 사용자로부터 정수를 하나 입력받아서, 그 값에 대해 다음 중 한가지 답변을 하도록 코드를 만들어보자.

   입력한 값은 0이거나 0보다 큽니다.

   입력한 값은 0보다 작습니다. 

 

▶ 문제 2. num에 저장된 값이 '1보다 크면서 동시에 5보다 작은가?'를 묻는 문장을 만들어서 다음 빈 공간을 채워보자.

   >>> num = 3

   >>> ___________________________________
   True



▶ 문제 3. 다음과 같이 변수를 선언하자.

   >>> num = 12

"num에 저장된 값은 3보다 작거나 10보다 큰가?"를 묻는 문장을 만들어보자.



▶ 문제 4. 다음과 같이 변수를 선언하자. 
    
   >>> num = 4

그리고 다음과 같이 묻는 문장을 만들어보자.
   "num에 저장된 값은 2의 배수이지만 3의 배수는 아니다. 맞는가?"



▶ 문제 5. 프로그램 사용자로부터 정수를 하나 입력받아서 그 값에 대해 다음 중 한가지 답변을 하도록 코드를 만들어보자.
  
   입력한 값은 0보다 작습니다.
   입력한 값은 0 이상 10 미만입니다.
   입력한 값은 10 이상 20 미만입니다.
   입력한 값은 20 이상입니다.

 

[7-7. 리스트와 문자열을 대상으로도 동작하는 >=, <=, ==, != 

- A >= Z : AZ와 같거나 크니?
- A <= Z : AZ가 같거나 작으니?
- A == Z : AZ가 같으니?
- A != Z : AZ가 다르니?

- == : 두 문자가 같으니? => True

- != : 두 문자가 다르니? => False

 

 

[7-8. True 또는 False로 답하는 함수들]

- s.isdigit() : 문자열 s가 숫자로만 이루어져 있으면 True, 아니면 False 반환
- s.isalpha() : 문자열 s가 알파벳으로만 이루어져 있으면 True, 아니면 False 반환
- s.startswith(prefix) : 문자열 sprefix로 시작하면 True, 아니면 False 반환
- s.endswith(suffix) : 문자열 ssuffix로 끝나면 True, 아니면 False 반환

- st1이 숫자로만 이루어져있는가? => True

- st2가 숫자로만 이루어져있는가? => False

 

- st1이 문자열로만 이루어져있는가? => False

- st2가 숫자로만 이루어져있는가? => True

 

- 문자열이 super로 시작되는가?

- 문자열이 int로 끝나는가?

 

 

[7-9. in, not in]

- s.find(sub) : 앞에서부터 sub를 찾아서 인덱스 값 반환
- s.rfind(sub) : 뒤에서부터 sub를 찾아서 인덱스 값 반환
- s.startwith(prefix) : prefix로 시작하면 True 반환
- s.endswith(suffix) : suffix로 끝나면 True 반환

- if s.find(“ghe”) != -1 : s“ghe”가 없으면 find 함수는 -1을 반환해라

 

- 굳이 저 연산자를 안 쓰고, in 함수를 사용해도 됨

- 그냥 문자열이 있는지 없는지만 확인하고 싶다 = in 함수

- 그 문자열의 존재 유무와 함께 위치 정보를 알고 싶다 = find 함수

 

- e in S : Se가 있으면 True, 없으면 False 반환
- e not in S : Se 가 없으면 True, 있으면 False 반환

 

 <연습문제 07-2>

▶ 문제1. 다음과 같이 동작하는 코드를 만들어보자.
    프로그램 사용자가 정수를 입력하면, 그 수의 거듭제곱의 값을 출력한다.
    프로그램 사용자가 정수가 아닌 것을 입력하면 "정수가 아닙니다."를 출력한다.
    코드는 다음의 구조로 작성하자. (main 함수를 만들고 이를 호출하는 방식)
       def main():
   
       main()

    물론 프롬프트상에서 만들어도 되고 소스파일을 생성해서 만들어도 된다. 

[6-1. 리스트와 함수들]

1) 리스트와 함수들

- len함수는 리스트에 저장된 값의 개수를 변환함

 

- len(s) : 리스트 s의 길이(저장된 값의 수) 반환
- min(s) : 리스트 s에 저장된 값 중에서 가장 작은 값 반환
- max(s) : 리스트 s에 저장된 값 중에서 가장 큰 값 반환

 

- 가장 작은 값과 가장 큰 값 반환 가능

- 뿐만 아니라 제거할 수도 있음

 

- s.append(x) : 리스트 s의 끝에 x를 추가
- s.extend(t) : 리스트의 s의 끝에 리스트 t의 내용 전부를 추가
- s.clear() : 리스트 s의 내용물 전부 삭제
- s.insert(i,x) : s[i]x를 저장
- s.pop(i) : s[i]를 반환 및 삭제
- s.remove(x) : 리스트 s에서 제일 앞에 등장하는 x를 하나만 삭제
- s.count(x) : 리스트 s에 등장하는 x의 개수 반환
- s.index(x) : 리스트 s에 처음 등장하는 x의 인덱스 값 반환

- 하나만 추가할 땐 append, 두 개 이상을 추가할 땐 extend 사용

- 삽입과 삭제

 

- 빈 리스트 하나 만들고 거기에 1, 9 추가

 

- popremove의 차이점

- pop은 삭제할 때 위치를 지정하는 반면, remove는 삭제할 값을 명시함

- st.pop(0) : 인덱스 값 0의 위치에 저장된 데이터 삭제

- st.remove(5) : 리스트에서 5를 삭제

 

 <연습문제 06-1>

▶ 문제 1. 다음은 빈 리스트를 만들어서 그 안에 1, 2, 3을 넣었다가 넣은 순서대로 꺼내는 코드의 실행 흐름이다.  실행 흐름이 완성되도록 빈칸에 문장들을 채워넣자.


▶ 문제 2. 위의 문제 1에서는 리스트에 다음 순서대로 값을 저장하고 꺼냈다. 
 - 저장 순서 : 1, 2, 3
 - 꺼낸 순서 : 1, 2, 3

 이번에는 다음 순서대로 값을 저장하고 꺼내도록 코드를 작성해보자.
 - 저장 순서 : 1, 2, 3
 - 꺼낸 순서 : 3, 2, 1


▶ 문제 3. 앞서 본문에서 리스트에 저장된 내용 전부를 삭제하는 clear 함수를 소개하였다. 그런데, 이렇듯 리스트에 저장된 값을 싹 비우는 방법을 앞서 5장에서도 소개한 바 있다. 슬라이싱 연산을 이용하는 방법인데, 이 방법을  이용하는 형태로 위의 코드를 수정해보자. 


▶ 문제 4. 빈 리스트를 만들어서 그 안에 1부터 10까지 넣었다가, 다시 1부터 10까지 꺼내는(삭제하는) 코드를 만들어보자. 단 이번에는 넣고 꺼내야 할 값이 많으니 for 루프를 이용하는 형태로 코드를 작성해보자.


▶ 문제 5. 빈 리스트를 만들어서 그 안에 1부터 10까지 넣었다가, 다시 10부터 1까지 꺼내는(삭제하는) 코드를 만들어보자. 이번에도 문제 4와 마찬가지로 for 루프를 이용하자. 


▶ 문제 6. 다음은 하나의 리스트에 다른 리스트의 값 전부를 추가하는 코드이다. 
   
   >>> st = [1, 2]
   >>> st.extend([3, 4, 5])
   >>> st
   [1, 2, 3, 4, 5]

위의 예에서는 extend 함수를 사용했는데, 이를 슬라이싱 연산을 이용하는 형태로 수정해보자. 다음 리스트에는 세 번째 값이 없다. 

   st = [1, 2]

그러나 다른 리스트이 값 전부를 추가할 때에는 세 번째 값이 있다고 가정하고 슬라이싱 연산을 전환하면 된다. 즉 세 번째 값을 리스트 [3, 4, 5]의 내용으로 교체하는 슬라이싱 연산문을 작성하면 된다. 

 

[6-2. 두 가지 유형의 함수가 갖는 특징들]

 

1) 두 가지 유형의 함수가 갖는 특징들

- len(s) : 리스트 s의 길이(s에 저장된 값의 수) 반환

 

- min(s) : 리스트 s에 저장된 값 중에서 가장 작은 값 반환

 

- max(s) : 리스트 s에 저장된 값 중에서 가장 큰 값 반환

 

- 문자열의 길이는?

 

- 알파벳 순서 중 가장 앞에 있는 문자는?

 

- 알파벳 순서 중 가장 뒤에 있는 문자는?

 

 

[6-3. 문자열과 함수들]

1) 문자열과 함수들

- s.count(sub) : 문자열 ssub가 등장하는 횟수 반환
- s.lower( ) : 문자열 s의 내용을 전부 소문자로 바꾼 문자열 변환
- s.upper( ) : 문자열 s의 내용을 전부 대문자로 바꾼 문자열 변환
- s.lstrip( ) : 문자열 s의 앞에 위치한 공백을 모두 제거한 문자열 반환
- s.rstrip( ) : 문자열 s의 뒤에 위치한 공백을 모두 제거한 문자열 반환
- s.strip( ) : 문자열 s의 앞과 뒤에 위치한 공백을 모두 제거한 문자열 반환
- s.replace(old, new) : 문자열 soldnew로 교체한 문자열 반환
- s.split( ) : 문자열 s를 공백을 기준으로 나눠서 리스트에 담아서 반환

 

 

- o가 몇 번 등장하는지?

- n이 몇 번 등장하는지?

 

- lcp : 모든 문자를 소문자로 바꿔서 변환하라

- ucp : 모든 문자를 대문자로 바꿔서 변환

- org : 원본은 그대로 존재

 

 <연습문제 06-2>

▶ 문제 1. 문자열 "The Espresso Spirit"을 다음과 같이 선언하자.
   >>> str = "The Espresso Spirit"
그리고 한 번은 모두 대문자로 바꿔서 출력하고, 또 한 번은 모두 소문자로 바꿔서 출력해보자. 그리고 마지막에 원본 그대로 출력을 한 번 더 하자. 


▶ 문제 2. 우리나라의 주민 번호는 다음과 같은 구조이다. 
 '070609-2011xxx'
 '090716-1012xxx'
이 중에서 앞의 여섯 자리는 생년월일 정보이다. 따라서 문자열로 표현된 위의 주민등록번호에서 생년 월일 정보만 꺼내서 출력하고자 하니, 이러한 기능을 제공하는 함수를 만들어보자. 예를 들어서 함수의 이름이 birth_only라 한다. 

 

 

1. 고체에 원자 구조 넣기

 - 크리스탈 고체는 우리가 원자를 연필로 찍어서 그릴 수 없음

 - 따라서 크리스탈 고체 안에 원자를 추가하는 방법은 두 가지로 나뉨

 - 좌표계가 정리되어있지 않아서 아톰을 찍어서 그릴 수 없음

 

  1) add atoms 탭 이용

   

- 좌표계 factional인지 잘 확인

- x,y,z 는 절대 좌표계임

- 각각의 끝을 1, 가운데는 0.5

 

 - 정 가운데에 원자 생성

 

 - 이미 선택한 분자에 이어 그리는 것은 가능함

 2) 우리가 그렸던 것을 그냥 copy해서 크리스탈 안에 붙여넣기 함으로써 원자 구조 추가하기

 

 

2. 고체 표면을 잘라 구조 만들기

- materials studio에서는 우리가 쓸만한 예시들을 미리 저장해놨음

- 그 구조에서 PT1 선택

- PT 구조가 생성된 것을 알 수 있고, 이는 원래 상자 하나만 보이지만, 사실 무수히 많은 상자들이 연결된 상태임

 - 따라서 MAX값을 몇으로 늘리느냐에 따라 붙어있는 직육면체 고체의 모습을 볼 수 있음

 

 

- build – cleave surface

- 실선으로 된 비스듬한 면으로 표면을 자르겠다는 의미임

- plaen을 설정해주면 어떻게 비스듬하게 자를 건지 설정할 수 있음

 

- 위와 같이 설정하면 다음과 같은 cleave surface를 얻을 수 있음

- 따라서 자르면 이런 형태의 모습이 됨

- 박스 구조가 아니라 평면 구조이기 때문에 OVU로 표시

 

- 다시 상자 구조 만들기 위해 vacuum 생성함

- vacuum thicknesscrystal thickness랑 연관되어 있음

: vacuum thickness는 얼만 큼 쌓아 올릴 건지 결정하는 값

: crystal thickness는 시작점부터 vacuum thickness까지의 길이

- 그래서 둘 중 하나를 선택하면 자동으로 한 값이 설정됨

 

- 다시 OABC가 됐음. 박스형이 된 것을 확인할 수 있음

- 여기에 mole구조를 넣을 건데, 지금 박스의 크기가 매우 작음

- 이렇게 작은 박스에 구조를 욱여넣어서 끝선에 닿거나 몰 분자끼리 너무 가깝게 있게 되면 실제로 계산했을 때 오류 발생함 è 값이 정확하지 않음

- 그래서 우리는 uni cell을 좀 더 키울 것!

- 슈퍼셀 만들어야 함

 

 - build – symmetry - supercell

 - 이렇게 커진 구조가 하나의 단위 셀이 되는 것

 

 

 

- 축 정렬

- 보는 방향 정렬

 

- 실제 보는 위치와 좌표의 위치를 동일하게 하려면 original 설정 (ex. 눈으로는 가운데에 위치한 것 같지만, 실제로 분자 구조에선 그렇지 않은 경우가 있음)

 

- 메탄 생성

 

- 고체 구조에 붙여넣기

 

- alt + shift + 우클릭 드래그를 통해 내가 원하는 특정 구조의 분자만 rotation

- 내가 원하는 위치에 놓으면 됨

 현재 튜토리얼상의 모습은 이러함

- 내가 만든 분자의 구조도 CPK로 설정하면 비슷한 양상을 띰

 - CPK : 반데르발스 결합을 상대적으로 부각시켜서, 시각화해서 보여주는 것

- 특정 거리만큼 특정 분자의 거리를 떨어뜨려 놓고 싶을 때

 

- 구조가 정렬된 상태에서, 상단의 layer만 선택

 

- best fit plane 클릭

 

- 그러면 plane이 하나 생성됨

 

 

 

 

 

 

 

 

 

 

 

 

 

 

- measure and change 틀 이용

- distance를 잴 것

 

- 거리를 설정할 수 있음

- 특정 거리를 설정해 주고 싶다면,

 하단의 상세 설정에서 거리 변경

1. 리스트 생성 방법

 - 리스트를 생성하는 방법

1 r1 = [1, 2, 3] 리스트를 생성하는 가장 일반적인 방법
2 r2 = [ ] 빈 리스트를 생성하는 방법
3 r3 = [1, 2, [3, 4]] 리스트가 포함된 리스트를 생성하는 방법

 

 - 리스트 함수를 호출해서 리스트를 생성하는 방법

1 r4 = list("Hello") 문자열을 전달해서 리스트를 생성
2 r5 = list((5, 6, 7)) 튜플을 전달해서 리스트를 생성
3 r6 = list(range(0,5)) 레인지를 전달해서 리스트를 생성

 

 - 그러나 조건이 복잡한 리스트를 만들 경우,

 ex) [1, 2, 3, 4, 5]의 모든 값을 두 배씩 증가시킨 값을 지니는 리스트를 만들어라.

 

 - 위와 같이 for 루프를 이용하면 됨

 - r2와 같이 일단 빈 리스트를 생성한 뒤에, 2씩 증가하여 리스트 r2에 저장하게끔 함

 

 

 

 - for 루프를 사용하지 않는 방법도 있는데, 그것이 리스트 컴프리헨션(Comprehension)’이라고 함

 - x *2 : 이 리스트의 값은 x * 2의 결과들로 이루어짐

 - for x in r1 : xr1에 있는 값들임

 - , r2 = [x * 2 for x in r1] : r1의 값들을 하나씩 x에 넣어서, x * 2의 결과를 만들어 리스트에 저장하겠음

 

 - [1, 2, 3, 4, 5]의 모든 값을 10씩 증가시킨 값을 지니는 리스트를 만들어라.

 

2. 조건 필터 추가 하기

 - i가 홀수인 경우에만 2를 곱하는 문장을 실행하는 조건이 달린 for 루프

 

 - 이를 리스트 컴프리헨션을 이용하여 작성하면,

 - for x in r1 : r1의 값들을 하나씩 x에 넣어서

 - if x % 2 : x % 2True인지 확인하고,

 - x * 2 : True이면 x * 2를 리스트에 추가하기

 

 - cf) 리스트 컴프리헨션은 일종의 규칙이므로 이해보다는 적용에 무게를 둬야함

 

 

3. 리스트 컴프리헨션에 for 한번 더 들어가는 경우

 - 옷의 상의와 하의의 색상 정보를 갖는 리스트를 만들고, 모든 조합의 색을 값으로 담는 리스트를 만들 경우 (확률과 통계 느낌)

r1 = [‘Black’, ‘White’’]
r2 = [‘Rec’, ‘Blue’, ‘Green’]

 

 - for 루프를 기반으로 하면,

 

 

- 이를 리스트 컴프리헨션으로 바꾸면,

 - for t in r1 for p in r2 : 모든 tp의 조합을 생성

 - t + p : t + p의 결과를 만들어서 리스트에 저장

 

 - 다음과 같은 리스트도 리스트 컴프리헨션을 이용하여 간단히 불러낼 수 있음

 - for n in range(2, 10) for m in range(1, 10) : 모든 nm의 조합을 생성해서

 - n * m : n * m의 결과를 만들어서 리스트에 저장해라

 

 

4. 이중 for 루프에 조건 필터 추가

 - 이중 for 루프 기반의 리스트 컴프리헨션도 if 절을 추가할 수 있음

 - 구구단의 결과를 담는 리스트에서 그 결과가 짝수인 값들만 리스트에 포함시키기

 - for n in range(2, 10) for m in range(1, 10)  : 모든 nm의 조합을 생성해서

 - if (n * m) % 2 : n * m의 결과가 2의 배수인 nm의 조합만을 가지고

 - n * m : n * m의 결과를 만들어서 리스트에 저장한다.

+ Recent posts