블로그 이미지
No pain, no gain!
lepoussin

Tag

Notice

Recent Post

Recent Comment

Recent Trackback

Archive

calendar

1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
  • total
  • today
  • yesterday
05-23 03:45
- 폰노이만 아키텍처 : 데이터용 버스와 명령어용 버스가 통합
- 하버드 아키텍처 : 데이토용 버스와 명령어용 버스가 분리

2.1 범용 레지스터(32비트) : 데이터나 주소 저장, 프로세서는 7개의 서로 다른 모드 상에서 동작(모드에 따라 r 다름), 한 번에 최대 18개 활성화 가능
  1) 데이터 레지스터(16개)
    - 특수 목적 레지스터
      r13 : 스택 포인터(sp), 현재 프로세서 모드의 스택 맨 위 주소값을 저장
      r14 : 링크 레지스터(lr), 코어가 서브루틴을 호출할 때마다 그 복귀 주소를 저장
      r15 : 프로그램 카운터(pc), 프로세서가 읽어들인 다음 명령어의 주소를 저장
      ※ r13, r14 범용 레지스터로 사용될 수 있기 때문에 이것들은 모드 변경 시 뱅크되어 저장(단, r13은 범용 레지스터 사용하면 위험)
  2) 프로그램 상태 레지스터(2개)
    - cpsr : 현재의 프로그램 상태 레지스터
    - spsr : 이전에 저장된 프로그램 상태 레지스터
  3) 레지스터 파일은 프로그래머가 이용할 수 있는 모든 레지스터들을 포함

2.2 CPSR 레지스터(32비트) : 내부 동작을 모니터링하고 제어
  1) 구분
    - 플래그(Flag) : 상태 플래그 저장
    - 상태(Status) : 미래에 사용할 목적으로 예약
    - 확장(Extension) : 미래에 사용할 목적으로 예약
    - 제어(Control) : 프로세서 모드와 상태, 인터럽트 마스크 비트
  2) 추가로 할당된 비트도 있음 ex) Jazelle : 8비트 자바 명령어

2.2.1 프로세서 모드
  1) 특권 모드(6개) : cpsr을 완전히 읽고 쓸 수 있는 모드
    - abort : 프로세서는 메모리 액세스가 실패했을 경우, abort 모드로 진입
    - FIQ, IRQ : 2가지 인터렙트 레벨을 위한 모드
    - supervisor : 프로세서에 리셋이 걸렸을 때에 진입하는 모드, 일반적으로 OS 커널이 동작하는 모드
    - system : user 모드의 특수 버전, cpsr을 완전히 읽고 쓸 수 있음
    - undefined : 프로세서가 정의되지 않은 명령어나 지원되지 않은 명령어를 만났을 때에 진입하는 모드
  2) 일반 모드 : 제어 필드만 읽기만 가능, 상태 플래그는 읽고 쓰기가 모두 가능
    - user : 프로그램과 어플리케이션을 위해 사용되는 모드

2.2.2 뱅크 레지스터
  1) 뱅크레지스터 : 레지스터 파일 내에 있는 37개의 레지스터 중 매번 프로그램에 따라 숨겨져 있는 20개
    - user 모드를 제외한 모든 프로세서 모드 : cpsr의 모든 비트를 직접 제어하여 모드 변경 가능
    - system 모드를 제외한 모든 모드 : 주요 16개 레지스터의 일부로 포함된 관련 뱅크 레지스터를 가짐
    - 뱅크 레지스터는 user 모드 레지스터에 하나씩 대응
    - 변경 시, old → new 대체
  2) 모드 변경
    - 해당 익셉션이나 인터럽트를 발생시키는 하드웨어에 의하거나 cpsr을 직접 제어
    - 모드 변경 익셉션 : reset, data abort, prefetch abort, undefined instruction
    - 익셉션과 인터럽트 : 현재 작업을 중단시키고 특정 위치로 분기, 이 경우에만 cpsr이 spsr에 저장(직접X)
  3) cpsr이 하위 5비트의 영역 차지 : 전원이 코어에 공급되면 이것은 특권 모드인 supervisor 모드에서 시작, 이는 초기화 코드가 다른 모드들을 위한 스택 셋업할 수 있도록 cpsr을 완전 액세스할 수 있기 때문에 매우 유용

2.2.3 프로세서 상태 및 명령어 세트
  1) 명령어 세트 종류(3가지) : 서로 섞어서 코딩할 수 없음
    - ARM 명령어 세트
    - Thumb 명령어 세트
    - Jazelle 명령어 세트
  2) 프로세서의 상태
    - Jazelle J와 Thumb T가 반영 : 둘 다 0이면 ARM 상태를 뜻함
    - 전원이 공급되는 순간은 항상 ARM 상태
    - cpsr T = 1, J = 0 : Thumb 상태
    - cpsr T = 0, J = 1 : Jazelle 상태
    - Jazelle(8비트 명령어 실행) : Java 코드의 실행 속도를 높이기 위함, 이것의 하드웨어 일부분은 Java 코드를 지원해야 하고 나머지는 소프트웨어적으로 에뮬레이션됨

2.2.4 인터럽트 마스크
  - 특정 인터럽트 소스가 프로세서에게 인터럽트 요청을 할 수 없도록 하기 위해 필요
  - cpsr 인터럽트 마스크 비트 : 6번(F : FIQ), 7번(I - IRQ)

2.2.5 상태 플래그
  1) 비교 명령어에 의해서 업데이트되거나 산술 명령어의 뒤에 s가 붙은 경우에 산술 처리 결과 업데이트됨
  2) DSP 확장 명령어를 포함하고 있는 프로세서 코어의 경우, Q비트 : 오버플로우나 포화 발생 검사(하드웨어에 의해서만 1로, cpsr에 직접 값을 써야 0으로 설정 가능)
  3) 종류
    - Q(Saturation) : 오버플로우나 포화가 발생하는 경우
    - V(oVerflow) : signed 오버플로우가 발생하는 경우
    - C(Carry) : unsigned 캐리가 발생하는 경우
    - Z(Zero) : 결과가 0인 경우, 종종 동일함을 표시하기 위해 사용
    - N(Negative) : 결과의 31번째 비트가 1인 경우

2.2.6 조건부 실행 : 어떤 명령어를 실행할 지의 여부를 제어할 수 있음
  1) 조건인자 : 코어가 대부분 명령어들의 실행할 지의 여부 결정하는데 사용
    - cpsr의 상태 플래그와 비교(동일하면 명령어 실행, 아니면 명령어 무시)
    - 명령어 니모닉 바로 뒤에 추가되어 명령어와 함께 인코드(만약 조건 인자가 없다면 AL(항상 실행)로 설정)

2.3 파이프라인
  1) 파이프라인의 구조
    - Fetch(메모리에서 명령어를 로드), Decode(실행한 명령어를 해독), Execute(명령어를 처리하고 그 결과를 레지스터에 저장)
    - 코어가 매 사이클마다 하나의 명령어를 실행시킬 수 있도록 해줌
  2) 파이프 라인 길이 ↑ : 각 단계에서 처리 가능한 일의 양 ↓(성능↑. but, 지연 ↑) → 명령어 스케줄링을 이용한 코드 작성 필요
  3) 파이프라인 길이 증가 제품군
    - ARM9(파이프라인 5단계) : Fetch → Decode → Execute → Memory → Write
    - ARM10(파이프라인 6단계) : Fetch → Issue → Decode → Execute → Memory → Write
    ※ ARM7을 위해 작성된 코드는 ARM9이나 ARM10에서도 그대로 실행 가능

2.3.1 파이프라인 동작 특성
  1) ARM7
  - 어떤 명령어가 실행 단계로 넘어오기 전까지는 그 명령어를 처리하지 않음(실행 단계를 완료하고 나서야 해당 명령어가 활성화, ARM 파이프라인 공통)
  - PC는 실행되고 있는 명령어의 주소보다 2단계(8) 앞선 주소를 가리킴
  - Thumb 상태에서는 프로세서의 PC값 == 명령어 주소 + 4
  2) 특징
    - 분기 명령어로 실행되거나  pc값을 직접 수정하여 분기하는 경우에는 파이프라인이 깨짐
    - ARM10은 분기 예측 방식 사용: 명령어를 실해하기 전에 가능한 분기를 미리 예측하여 새로운 분기 주소를 로드 → 파이프라인이 깨지는 상황 감소
    - 실행 단계에 있는 명령어는 인터럽트가 발생하더라도 그 과정을 완료

2.4 ARM 프로세서에서의 익셉션
  1) 벡터 테이블
    - 익셉션이나 인터럽트가 발생하였을 때, 프로세서가 pc에 넣는 특정 메모리 주소값들이 포함된 특정 주소 영역
    - 특정 루틴으로 분기하는 명령어들 존재
    - 메모리맵 주소 0x00000000는 벡터 테이블들을 위해 32비트 워드값들로 예약(0xffff0000에서 시작도 가능)
  2) 익셉션 테이블 엔트리
    - Reset Vector : 전원이 공급될 때 프로세서에 의해 처음으로 실행되는 명령어의 위치
    - Undefined Instruction vector : 프로세서가 명령어를 분석할 수 없을 때에 사용
    - Software Interrupt vector : SWI 명령어를 실행시켰을 때에 호출
    - Prefetch Abort vector : 프로세서가 정확한 접근권한 없이 어던 주소에서 명령어를 읽어들이려고 시도할 때 발생
    - Data Abort vector : 명렁어가 정확한 접근권한 없이 데이터 메모리를 액세스하려고 시도할 때 발생
    - Interrupt Request vector : 프로세서의 현재 흐름을 중단시키기 위해 외부 하드웨어 장치에 의해 사용
    - Fast Interrupt Request vector : IRQ와 유사하나 더욱 빠른 응답 시간을 요구하는 하드웨어를 위해 할당

2.5 캐시 메모리와 코프로세서
  - 하드웨어의 확장은 특정 어플리케이션을 다루는 데 있어서 유연성을 제공하기 위해 설계
  - 각 제품군은 확장된 부분이 서로 다름

2.5.1 캐시와 TCM
  1) 캐시 : 성능 향상시켜 주지만 예측성 감소 시킴(그래서 이것을 이용한 성능의 향상 필요로 하지 않음)
    - 폰노이만 형태 : 명령어와 데이틀 통합 캐시에 함께 저장
    - 하버드 형태 : 명령어와 데이터를 위한 캐시 분리
  2) TCM : 코어 가까이에 위치한 빠른 SRAM으로, 명령어나 데이터를 읽어들이는 데 필요한 클럭 사이클(확정적 동작에 필요한 실시간 알고리즘을 위해 필수적)을 보장 → 코드 실행의 확정성(deterministic) 향상
  3) 로직 제어 장치(logic and control) : 메모리 시스템을 AMBA 버스에 연결해주는 논리 장치

2.5.2 메모리 관리
  1) 일반 관리 장치(no extensions providing no protection)
    - 비보호 메모리(nonprotected memory): 고정적, 유연성 거의 없음
  2) 메모리 보호 장치(MPU) : 제한된 수의 메모리 영역을 사용한 간단한 시스템에 적용
  3) 메모리 관리 장치(MMU) : ARM에서 사용되는 가장 복잡한 메모리 관리 장치
    - 변환 테이블(접근권한, 가상 메모리 매핑 기능) 세트 사용 : 세밀한 제어 가능
    - 멀티태스킹을 지원하는 복잡한 플랫폼 OS를 위해 설계

2.5.3 코프로세서
  - ARM 프로세서에 부착하여 사용
  - 로드-스토어 타입의 인터페이스를 제공해주는 전용 ARM 명령어를 통해 액세스 가능
  - 새로운 특정한 명령어들을 제공하여 명령어 세트를 확장 가능(새로운 명령어들은 디코드 단계(파이프라인)에서 처리)

2.6 아키텍처 버전
  - 모든 ARM 프로세서는 특정 ISA(Instruction Set Architecture)로 구현

2.6.1 명명법
  1) ARM 명명법
    ARM{x}{y}{z}{T}{D}{M}{I}{E}{J}{F}{-S}
    x : 제품군
    y : MMU/MPU
    z : 캐시
    T : Thumb 16비트 디코더
    D : JTAG 디버그
    M : 고속 곱셈기
    I : EmbeddedICE macrocell
    E : DSP 확장 명령어
    J : Jazelle
    F : VFP 장치
    S : synthesizable 버전
  2) 추가 사항
    - ARM7TDMI 이후에 나온 모든 ARM 코어에는 자동적으로 TDMI 특징 포함
    - 프로세서 제품군(family)은 동일한 하드웨어 특징을 보이는 프로세서 집합을 의미
    - JTAG : 프로세서 코어와 테스트 장비간에 디버깅 정보를 전송하기 위해 ARM에서 적용한 시리얼 프로토콜
    - EmbeddedICE macrocell : 프로세서에 내장되어 있는 디버그 하드웨어 장치, breakpoint와 watchpoint 설정 가능
    - synthesizable : 프로세서 코어가 EDA 툴에 의해 쉽게 사용 가능한 형식, 컴파일될 수 있는 소스 코드로 공급된다는 것을 의미

2.6.2 아키텍처의 발전
  - 1~v6
  - ARMv4(ARM7TDMI)에서 Thumb 명령어 세트 지원

2.7 ARM 프로세서의 버전별 특징
  - 제조 환경은 주파수(MHz)와 전력 소모(watts)에 직접적으로 영향을 주기 때문

2.7.1 ARM7 군
  1) 특징
    - 폰노이만 아키텍쳐
    - 3단 파이프라인
    - ARMv4T 명령어 세트
  2) 종류
    - ARM7TDMI : 가장 인기, Thumb 명령어 세트, 빠른 곱셈 명령어, EmbeddedICE 디버그 기술 포함
    - ARM720T : 리눅스나 마이크로소프트 임베디드 OS 사용 가능
    - ARM7EJ-S : 5단 파이프라인, MPU 내장X

2.7.2 ARM9 군
  1) 특징
    - 하버드 아키텍처
    - 5단계 파이프라인
  2) 종류
    - ARM940T : MMU 내장, 가상 메모리의 지원이 필요한 운영체제를 위해 사용
    - ARM9E-s : synthesizable, ETM(Embedded Trace Macrocell)
    - ARM946E-S : TCMㆍ캐시(이 2개는 크기 조절 가능)ㆍMPU 포함, 확정적인 실시간 응답성을 요구하는데 임베디드 제어 어플리케이션에서 사용
    - ARM966E : MPU와 캐시를 가지고 있지 않음, TCM은 조절 가능
    - ARM926EJ-S : 3G 폰ㆍPDA와 같은 작고 휴대 가능한 java를 지원하는 장치를 위해 설계

2.7.3 ARM10 군
  1) 특징
    - 6단계 파이프라인
    - VFP(Vector Floating-Point) 장치 지원 → 7번째 단계 추가 가능
  2) 종류
    - ARM1020E : 듀얼 64비트 버스 인터페이스를 지원
    - ARM1026EJ-S : ARM926EJ-S와 유사하지만 MPU와 MMU 보유

2.7.4 ARM11 군
  1) 종류
    - ARM1136J-S : 고성능 저전력의 어플리케이션을 위해 설계, 8단 파이프라인, ARMv6(미디어 처리를 향상시킬 수 있는 SIMD(Single Instruction Multiple Data) 확장 명령어 포함) 명렁어
    - ARM1136JF-S : ARM1136J-S에 VFP 장치 포함

2.7.5 이외의 특별한 제품군
  - StrongARM : 저전력 소모와 고성능을 필요로 하는 PDA와 어플리케이션에 좋음, 하버드 아키텍처, 5단 파이프라인, Thumb 명령어 지원 안함
  - XScale : 1GHz 속도(책 저자 집필 시점), v5TE 명령어, 하버드 아키텍처, MMU 내장
  - SC100 : 저전력 보안 장치위해 설계, ARM7TDMI 기반, MPU 내장, 스마트카드 어플리케이션에 응용 가능
posted by lepoussin
1.1 RISC의 특징
  1) RISC
    - 매우 빠른 속도로 한 클럭 안에 실행될 수 있는 간결하면서도 막강한 명령어들을 가지고 있는 아키텍처
    - 하드웨어에 의해 수행되는 명령어들의 복잡도를 줄이는 것이 목표(S/W의 유연성과 복잡성 감소)
    - 컴파일러에 더욱 의존함
  2) 설계 방식
    - 명령어 : 상대적으로 적은 수의 명령어군, 일정한 길이 가짐
    - 파이프라인 : 병렬로 실행될 수 있는 작은 단계로 쪼개져 실행
    - 레지스터 : 거대한 레지스터군
    - Load-Store 아키텍쳐 : 레지스터 활용하여 메모리 액세스 감소
  3) 더욱 단순화되어 더 빠른 클럭으로 동작

1.2 ARM 프로세서의 특징
  - 배터리 전력 요구
  - 코드의 고집적도 : 비용이나 물리적인 크기의 제약으로 제한된 메모리를 가지고 있기 때문
  - 속도가 느린 저가격의 메모리 소자 사용
  - 프로세서 내분에 하드웨어 디버그 기술 포함
  - 순수한 RISC 아키텍처를 채택하고 있지는 않음(임베디드 시스템에 국한되어 있기 때문) : 속도가 아닌 전체적으로 효율적인 시스템 성능 및 전력 소모에 근원

1.2.1 임베디드 시스템을 위한 명령어 세트
  1) 가변 사이클로 실행되는 명령어
  2) 복잡한 명령어 처리를 위한 인라인 배럴 시프터(Inline Barrel Shifter) : 명령어에 의해 사용되기 전에 그 입력 레지스터 중의 하나를 미리 처리
  3) 16비트 Thumb 명령어 : 16비트 or 32비트 명령어로 실행
  4) 조건부 실행
  5) DSP 확장 명령어 : 빠른 16x16비트의 곱셈 처리를 지원하기 위해 디지털 신호 처리(DSP) 확장 명령어 추가
 
1.3 ARM 하드웨어 임베디드 시스템 아키텍쳐
  - ARM 프로세서 : 임베디드 디바이스 제어, 원하는 동작 특성에 맞게 선택하여 사용
  - 컨트롤러 : 주요 기능을 담담하는 블록(인터럽트 컨트롤러, 메모리 컨트롤러 등)
  - 주변 장치 : 칩 외부로 입출력 기능 제공
  - 버스 : 주변 장치간의 통신 담당

1.3.1 ARM 버스 기술 : 칩 내부 버스 사용
  1) 종류
    - 버스 마스터 : 다른 디바이스로 데이터를 전송할 수 있는 논리 장치
    - 버스 슬레이브 : 버스 마스터로부터 전송 요청이 있을 때에만 동작
  2) 버스 아키텍처 구성
    ① 전기적인 특성과 버스폭(16, 32, 64비트)을 담당하는 물리적인 단계
    ② 프로토콜 처리 단계

1.3.2 AMBA(Advanced Microcontroller Bus Architecture) 버스 프로토콜
  - ASB(ARM System Bus), APB(ARM Peripheral Bus), AHB(ARM High Performance Bus)
  - 사용성과 타임 투 마켓 향상
  - AHB : 한방향에 집중된 멀티플레스 버스 기반, 많은 데이터량 처리(64, 128비트폭 지원), 매우 빠른 속도
    1) 오리지날 AHB : 한번에 하나의 버스 마스터만 활성화
    2) Multi-layer AHB : 동시에 여러 개의 버스 마스터를 활성화 상태로 만듦, 멀티프로세서 시스템에 적합
    3) AHB-lite : AHB 버스의 하위셋으로 하나의 버스 마스터로 한정, 표준 AHB 버스의 모든 특성을 요구하지 않는 디자인
    ※ AHB와 Multi-layer AHB는 동일한 프로토콜을 지원하지만 연결 방식이 서로 다르다.

1.3.3 메모리
  1) 메모리 계층 구조
    - 캐시 : 일반적인 성능 향상은 가져오지만 실시간 시스템 응답에는 도움을 주지 못함(임베디드 포함)
    - 주메모리 : 별도 외부의 칩 사용
    - 보조 기억 장치 : 가장 크고 느린 메모리 형태
  2) 메모리폭 : 한 번에 액세스할 수 있는 비트의 수
    - 전체적인 성능 대 가격비에 직접적인 영향, Thumb 명령어 사용을 통해 개선 가능
  3) 메모리의 종류
    - ROM(Read-Only Memory)
    - 플래시롬
    - DRAM(Dynamic Random Access Memory) : 리프레시 작업을 해주어 데이터를 지속적으로 충전 필요
    - SRAM(Static Random Access Momory) : 리프레시 작업 필요 없음
    - SDRAM(Synchronous Dynamic Random Access Memory) :프로세서 버스와 동기화하여 동작

1.3.4 주변 장치
  1) 메모리 컨트롤러 : 다양한 유형의 메모리를 프로세서 버스에 연결해주는 역할
  2) 인터럽터 컨트롤러 : 주변 장치나 디바이스가 실행되려고 할 때, 프로세서에게 인터럽트를 발생
    - 표준 인터럽터 컨트롤러 : 서비스 요청 시, 그 인터럽트 신호를 프로세서 코어에 보냄, 디바이스 비트맵 레지스터 이용
    - 벡터 인터럽트 컨트롤러(VIC) : 인터럽트에 우선 순위 부여, 핸들러 주소 살펴본 후 높은 우선순위인 경우만 프로세서에게 인터럽트 신호 보냄

1.4 소프트웨어 계층 구조
  1) 초기화 코드 : 리셋 이후 운영체제가 실행될 수 있는 상태로 만들어주는 역할
    - 설정 코드 : OS 이미지를 부팅할 수 있도록 타겟 플랫폼을 설정하는 일 담당
    - 진단 코드 : 순서대로 처리하고 있는지 확인하기 위해 하드웨어 시스템 테스트, 문제 찾음
    - 부팅 코드 : 이미지를 로드한 후 그 이미지로 제어권을 넘겨주는 작업(PC를 이미지의 시작 위치로 이동)
    - 메모리 리매핑 : 전원이 공급되면 초기화 곧바로 실행되어야 하기 때문
  2) 운영체제
    - 시스템 리소스 조직(주변 장치, 메모리 처리 시간 등)
    - RTOS : 이벤트에 대한 반응 시간을 보장해야만 함, hard/soft 구분, 일반적으로 보조 저장 장치 불필요
    - 플랫폼 OS: 규모가 크고 실시간성을 요하지 않는 어플리케이션 관리 → MMU 필요, 보조 저장 장치 필요
  3) 어플리케이션 : 환경 제어(어플리케이션을 스케줄링)
posted by lepoussin
2007. 2. 24. 22:55 Lecture/열혈강의 Python

1. 사전 객체의 기초 연산
  - 내부적으로 해쉬(Hash)라는 기법을 이용하여 자료 저장
  - 자료의 순서를 가지지 않는다.
  - 값은 임의의 객체가 될 수 있지만, 키는 변경 불가능(Immutable) 자료형이어야 한다.
  - 문자열, 숫자, 튜플은 키가 될 수 있지만 리스트, 사전은 키가 될 수 없다.

>>> member = {'basketball': 5, 'soccer':11, 'baseball':9}
>>> member['baseball'] # 검색
9
>>> member['volleyball'] = 7 # 새 값 설정
>>> member
{'soccer': 11, 'basketball': 5, 'baseball': 9, 'volleyball': 7}
>>> member['volleyball'] = 10 # 변경
>>> member
{'soccer': 11, 'basketball': 5, 'baseball': 9, 'volleyball': 10}
>>> len(member) # 길이
4
>>> del member['baseball'] # 항목 삭제
>>> def add(a, b):
 return a+b

>>> def sub(a, b):
 return a-b

>>> action = {0:add, 1:sub} # 함수를 키나 값으로 활용
>>> action[0](4, 5)
9
>>> action[1](4, 5)
-1

※ 다양한 방법으로 사전 객체 생성하기

>>> dict() # 빈 사전 생성
{}
>>> dict(one=1, two=2) # 키워드 인수를 지정하여 사전 생성
{'two': 2, 'one': 1}
>>> dict([('one', 1), ('two', 2)]) # (key, value) 쌍의 시퀀스로부터 사전 생성
{'two': 2, 'one': 1}
>>> dict({'one':1, 'two':2}) # 사전 객체를 인수로 받아 새로운 사전 생성
{'two': 2, 'one': 1}
>>> keys = ['one', 'two', 'three']
>>> values = (1, 2, 3)
>>> zip(keys, values) # zip은 자료를 순서대로 묶어줌
[('one', 1), ('two', 2), ('three', 3)]
>>> dict(zip(keys, values))
{'three': 3, 'two': 2, 'one': 1}

2. 사전 객체의 메쏘드

>>> phone = {'jack': 9465215, 'jim': 1111, 'Joseph': 6584321}
>>> phone.keys() # 키의 리스트를 반환
['jim', 'Joseph', 'jack']
>>> phone.values() # 값의 리스트를 반환
[1111, 6584321, 9465215]
>>> phone.items() # (키, 값)의 리스트를 반환
[('jim', 1111), ('Joseph', 6584321), ('jack', 9465215)]
>>> 'jack' in phone # 'jack'이 phone의 키에 포함되어 있는가?
True
>>> 'lee'in phone
False
>>> p = phone # 사전 레퍼런스 복사(사전 객체는 공유됨)
>>> phone['jack'] = 1234 # 변경
>>> phone
{'jim': 1111, 'Joseph': 6584321, 'jack': 1234}
>>> p # phone과 동일하게 변경됨
{'jim': 1111, 'Joseph': 6584321, 'jack': 1234}
>>> ph = phone.copy() # 사전 복사(별도의 사전 객체를 리턴)
>>> phone['jack'] = 1111 # 변경
>>> ph # phone과 다른 객체이기 때문에 변경 안되었음
{'jim': 1111, 'Joseph': 6584321, 'jack': 1234}
>>> ph.get('jack') # 'jack'키에 대한 값을 얻음
1234
>>> ph.get('creaplz') # 값이 없는 경우 None을 리턴
>>> ph['creaplz'] # ph['creaplz']는 값이 없는 경우 예외를 발생 

Traceback (most recent call last):
  File "<pyshell#98>", line 1, in <module>
    ph['creaplz']
KeyError: 'creaplz'

>>> ph.get('creaplz', 510) # 인수를 하나 더 써주면, 존재하지 않는 키인데도 지정한 인수를 리턴
510
>>> ph # 사전에는 변화 없음
{'jim': 1111, 'Joseph': 6584321, 'jack': 1234}
>>> ph.setdefault('creaplz', 510) # 'creaplz'의 값을 꺼내되, 없으면 510로 설정
510
>>> ph # 'creaplz': 510이 설정
{'jim': 1111, 'Joseph': 6584321, 'jack': 1234, 'creaplz': 510}
>>> ph.popitem() # 한 아이템을 꺼냄
('jim', 1111)
>>> ph.popitem() # 또 한 아이템을 꺼냄
('Joseph', 6584321)
>>> ph # popitem 결과
{'jack': 1234, 'creaplz': 510}
>>> ph.pop('jack') # 지정한 키를 pop
1234
>>> ph
{'creaplz': 510}
>>> phone.update(ph) # 사전 phone의 내용을 ph으로 추가 갱신
>>> phone
{'jim': 1111, 'Joseph': 6584321, 'jack': 1234, 'creaplz': 510}
>>> phone.clear() # 사전의 모든 입력을 제거
>>> phone
{}

3. 심볼 테이블

>>> a = 1
>>> b = 100
>>> name = 'creaplz'
>>> dic = {'Python': 'Good', 'Perl': 'Not Good'}
>>> globals() # 전역 영역(모듈 영역)의 심볼 테이블(사전) 얻음
{'a': 1, 'b': 100, 'name': 'creaplz', '__builtins__': <module '__builtin__' (built-in)>, 'dic': {'Python': 'Good', 'Perl': 'Not Good'}, '__name__': '__main__', '__doc__': None}
>>> locals() # 지역 영역의 심볼 테이블 얻음(대화형 최상위 모드에서는 globals()와 별 차이가 없음)
{'a': 1, 'b': 100, 'name': 'creaplz', '__builtins__': <module '__builtin__' (built-in)>, 'dic': {'Python': 'Good', 'Perl': 'Not Good'}, '__name__': '__main__', '__doc__': None}
>>> # 객체의 심볼 테이블
>>> class C:
 x = 10
 y = 20

>>> C.__dict__ # 클래스의 심볼 테이블 얻음
{'y': 20, 'x': 10, '__module__': '__main__', '__doc__': None}
>>> c = C() # 객체 생성
>>> c.a = 100
>>> c.b = 200
>>> c.__dict__ # 클래스 인스턴스의 심볼 테이블 얻음
{'a': 100, 'b': 200}
>>> def f():
 pass
>>> f.a = 1
>>> f.b = 2
>>> f.__dict__ # 함수의 심볼 테이블 얻음
{'a': 1, 'b': 2}


4. 사전을 for문으로 참조하기

>>> D = {'a': 1, 'b': 2, 'c': 3}
>>> for key in D: # 사전 자체 이용
 print key, D[key]


a 1
c 3
b 2

>>> for key, value in D.items():
 print key, value


a 1
c 3
b 2

>>> items = D.items()
>>> items.sort() # 순서 정렬(키 기준)
>>> items
[('a', 1), ('b', 2), ('c', 3)]
>>> for k, v in items:
 print k, v


a 1
b 2
c 3

>>> # 정렬된 결과를 한번만 이용하기
>>> for key, value in sorted(d.items()): # 순서 정렬(키 기준)
 print key, value


one 1
three 3
two 2

>>> for key, value in sorted(d.items(), key=lambda item:item[1]): # 순서 정렬(값 기준)
 print key, value


one 1
two 2
three 3

posted by lepoussin
2007. 2. 24. 20:33 Lecture/열혈강의 Python

1. 튜플의 연산

>>> t = () # 공 튜플
>>> t = (1, 2, 3) # 괄호 사용
>>> t = 1, 2, 3
>>> r = (1,)
>>> r = 1, # 괄호는 없어도 콤마(,)는 무조건 있어야 함
>>> t * 2 # 반복
(1, 2, 3, 1, 2, 3)
>>> t + ('PyKUG', 'user') # 연결
(1, 2, 3, 'PyKUG', 'user')
>>> print t[0], t[1:3] # 인덱싱, 슬라이싱
1 (2, 3)
>>> len(t) # 길이
3
>>> 1 in t # 멤버십 테스트
True
>>> t[10] = 100 # 튜플은 변경 불가능(Imumutable) 자료형

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    t[10] = 100
TypeError: 'tuple' object does not support item assignment

>>> t = (1, 2, 3)
>>> u = t, 4, 5 # 중첩
>>> u
((1, 2, 3), 4, 5)
>>> x, y = 1, 2 # 복수개의 자료 치환
>>> x, y = y, x # swap
>>> x, y
(2, 1)

2. 패킹과 언팩킹

>>> # 튜플
>>> t = 1, 2, 'hello' # 팩킹
>>> x, y, z = t # 언팩킹
>>> # 리스트
>>> a = ['foo', 'bar', 4, 5] # 팩킹
>>> [x, y, z, w] = a # 언팩킹

3. 리스트와의 공통점과 차이점
  1) 공통점
    - 임의의 객체를 저장할 수 있다
    - 시퀀스 자료형(인덱싱, 슬라이싱, 연결, 반복 지원)
  1) 차이점
    - 문자열과 같은 변경 불가능(Immutable) 시퀀스형이다. 따라서 아이템을 변경하려면 슬라이싱과 연결(Concatenation)을 이용해야 한다.
    - 메쏘드를 가지지 않는다.
  3) 상호 변환

>>> T = (1, 2, 3, 4, 5)
>>> L = list(T)
>>> L[0] = 100
>>> L
[100, 2, 3, 4, 5]
>>> T = tuple(L)
>>> T
(100, 2, 3, 4, 5)

4. 튜플 사용하는 경우
  1) 함수에 있어서 하나 이상의 값을 리턴하는 경우

>>> def calc(a, b):
 return a+b, a-b

>>> x, y = calc(5, 4)

  2) 문자열 포매팅

>>> print 'id : %s, name : %s' % ('creaplz', 'hong')
id : creaplz, name : hong

  3) 튜플에 있는 값들을 함수 인수로 사용할 때(가변 인수)

>>> args = (4, 5)
>>> calc(*args)
(9, -1)

  4) 고정된 값을 표현

>>> d = {'one': 1, 'two': 2}
>>> d.items()
[('two', 2), ('one', 1)]
posted by lepoussin
2007. 2. 24. 14:16 Lecture/열혈강의 Python

1. 리스트의 일반 연산

>>> l = [] # 공 리스트
>>> l = [1, 2, "Great"]
>>> print l[0], l[-1] # 인덱싱
1 Great
>>> print l[1:3], l[:] # 슬라이싱
[2, 'Great'] [1, 2, 'Great']
>>> L = range(10)
>>> L[::2] # 확장 슬라이싱
[0, 2, 4, 6, 8]
>>> l * 2 # 반복
[1, 2, 'Great', 1, 2, 'Great']
>>> l + [3, 4, 5] # 연결
[1, 2, 'Great', 3, 4, 5]
>>> len(l) # 길이
3
>>> 4 in L # 멤버십 테스트
True
>>> l[1] = l[1] + 23 # 변경
>>> l
[1, 25, 'Great']
>>> l[0:2] = [5, 10]  # 교체(슬라이스에서는 양쪽변의 크기가 달라도 됨)
>>> l
[5, 10, 'Great']
>>> l[0:2] = [] # 공 리스트를 이용한 삭제
>>> l
['Great']
>>> a = range(10)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[0] # del을 이용한 삭제
>>> del a[1:]
>>> a
[1]
>>> a = range(4)
>>> del a[::2]
>>> a
[1, 3]
>>> a = [123, 1234]
>>> a[1:1] = ['spam', 'ham'] # 슬라이스 삽입
>>> a
[123, 'spam', 'ham', 1234]
>>> a[:0] = a # 제일 앞에 추가
>>> a
[123, 'spam', 'ham', 1234, 123, 'spam', 'ham', 1234]
>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> a[::2] = range(0, -2, -1) # 교체(확장 슬라이스에서는 양쪽변의 개수가 맞아야 함)
>>> a
[0, 1, -1, 3]
>>> a[::2] = range(3)

Traceback (most recent call last):
  File "<pyshell#25>", line 1, in <module>
    a[::2] = range(3)
ValueError: attempt to assign sequence of size 3 to extended slice of size 2


2. 중첩 리스트
>>> L = [1, ['a', ['x', 'y'], 'b'], 3]
>>> L[0]
1
>>> L[1]
['a', ['x', 'y'], 'b']
>>> L[1][1]
['x', 'y']
>>> L[1][1][1]
'y'

3. 리스트의 메쏘드들
>>> s = [1, 2, 3]
>>> s.append(5)
# 리스트 마지막에 추가
>>> s
[1, 2, 3, 5]
>>> s.insert(3, 4) # 3 위치에 4 삽입
>>> s
[1, 2, 3, 4, 5]
>>> s.index(3) # 값 3의 위치는?
2
>>> s.count(2)
# 값 2의 개수는?
1
>>> s.reverse()
# 순서 뒤집기(리턴 값 없음)
>>> s
[5, 4, 3, 2, 1]
>>> s.sort()
# 정렬(리턴 값 없음)
>>> s
[1, 2, 3, 4, 5]
>>> s.remove(3)
# 3 삭제(제일 처음 것 1개만 삭제됨)
>>> s
[1, 2, 4, 5]
>>> s.extend([6, 7]) # 리스트를 추가
>>> s
[1, 2, 4, 5, 6, 7]
>>> s.pop()
# 기본적으로 마지막 자료 pop
7
>>> s
[1, 2, 4, 5, 6]
>>> s.pop(0)
# 위치 지정 가능
1
>>> s
[2, 4, 5, 6]


4. 튜플 혹은 리스트의 리스트 반복 참조하기

>>> lt = [('one', 1), ('two', 2), ('three', 3)]
>>> for t in lt:
 print 'name=', t[0], 'num=', t[1]


name= one num= 1
name= two num= 2
name= three num= 3

>>> for t in lt:
 print 'name=%s, num=%s' % t


name=one, num=1
name=two, num=2
name=three, num=3

>>> for name, num in lt:
 print name, num


one 1
two 2
three 3

5. 원하는 순서대로 정렬하기

>>> L = [1, 5, 3, 9, 8, 4, 2]
>>> newList = L.sort() # 리턴되는 값이 없음(자체 변경)
>>> print newList
None
>>> L # 자체 변경됨
[1, 2, 3, 4, 5, 8, 9]
>>> cmp(1, 2)
-1
>>> cmp(5, 2)
1
>>> cmp('abc', 'abc')
0
>>> def mycmp(a1, a2):
 return cmp(a2, a1)

>>> L = [1, 5, 3, 2, 4, 6]
>>> L.sort(mycmp) # 비교 함수 변경
>>> L
[6, 5, 4, 3, 2, 1]
>>> L = [1, 6, 3, 8, 6, 2, 9]
>>> L.sort(reverse=True) # 역순 정렬 지원
>>> L
[9, 8, 6, 6, 3, 2, 1]
>>> L = ['123', '34', '56', '2345']
>>> L.sort()
>>> L
['123', '2345', '34', '56']
>>> L.sort(key=int) # 비교 키를 지원
>>> L
['34', '56', '123', '2345']
>>> # sorted 내장 함수
>>> L = [1, 6, 3, 8, 6, 2, 9]
>>> newList = sorted(L) # L은 변경 내용이 없고, 새로운 리스트가 리턴
>>> newList
[1, 2, 3, 6, 6, 8, 9]
>>> newList = sorted(L, reverse=True)
>>> newList
[9, 8, 6, 6, 3, 2, 1]
>>> L = ['123', '34', '56', '2345']
>>> sorted(L, key=int)
['34', '56', '123', '2345']
>>>
# reversed 내장 함수
>>> newList = reversed(L)
# L은 변경 내용이 없고, 반복자(Iterator)가 리턴
>>> newList
<listreverseiterator object at 0x00DAACF0>
>>> for ele in reversed(L):
 print ele


2345
56
34
123

6. 리스트 내장

>>> # 10보다 작은 정수 중 홀수의 제곱만 리턴하는 예
>>> L = [k * k for k in range(10) if k % 2]
>>> L
[1, 9, 25, 49, 81]
>>> # 2의 배수와 3의 배수 중 두수의 합이 7의 배수가 되는 두 수의 곱의 리스트 만드는 예
>>> [(i, j, i*j) for i in range(2, 100, 2)
 for j in range(3, 100, 3)
 if (i+j) % 7 == 0]
[(2, 12, 24), (2, 33, 66), (2, 54, 108), (2, 75, 150), (2, 96, 192), (4, 3, 12), (4, 24, 96), (4, 45, 180), (4, 66, 264), (4, 87, 348), (6, 15, 90), (6, 36, 216), (6, 57, 342), (6, 78, 468), (6, 99, 594), (8, 6, 48), (8, 27, 216), .. 출력 생략.. , (98, 63, 6174), (98, 84, 8232)]
>>> # 리스트 내장 효과의 발생자
>>> sum(x*x for x in range(10)) # 메모리를 내장하는 새로운 리스트를 생성 안함
285
>>> (x*x for x in range(10)) # 발생자(Generator) 생성
<generator object at 0x00DC3D78>
>>> sum([x*x for x in range(10)]) # 새로운 리스트를 생성하여 sum 연산
285

7. 순환 참조 리스트

>>> GNU = ['is not Unix']
>>> GNU.insert(0, GNU)
>>> GNU

[[...], 'is not Unix']
>>> GNU[0]
[[...], 'is not Unix']
>>> GNU[0][0]
[[...], 'is not Unix']
>>> GNU[0][0][0]
[[...], 'is not Unix']

8. 순차적인 정수 리스트 만들기

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(5, 15)
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> range(5, 15, 2)
[5, 7, 9, 11, 13]
>>> range(0, -10, -1)
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
 
>>> sun, mon, tue, wed, thu, fri, sat = range(7)

9. 배열 표현

>>> mat = [[0] * 4] * 3
>>> mat
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> mat[0][0] = 100
>>> mat
[[100, 0, 0, 0], [100, 0, 0, 0], [100, 0, 0, 0]]
>>> mat = [[0]*4 for x in range(3)]
>>> mat
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> mat[0][0] = 100
>>> mat
[[100, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

※ arrary,  NumPy 모듈 사용하여 고수준의 행렬 표현 및 연산 가능
 

posted by lepoussin