diff options
Diffstat (limited to 'ko-kr')
-rw-r--r-- | ko-kr/javascript-kr.html.markdown | 435 | ||||
-rw-r--r-- | ko-kr/lua-kr.html.markdown | 424 | ||||
-rw-r--r-- | ko-kr/python-kr.html.markdown | 484 |
3 files changed, 1343 insertions, 0 deletions
diff --git a/ko-kr/javascript-kr.html.markdown b/ko-kr/javascript-kr.html.markdown new file mode 100644 index 00000000..e5517aa8 --- /dev/null +++ b/ko-kr/javascript-kr.html.markdown @@ -0,0 +1,435 @@ +--- +language: javascript +category: language +contributors: + - ["Adam Brenecki", "http://adam.brenecki.id.au"] +translators: + - ["wikibook", "http://wikibook.co.kr"] +lang: ko-kr +--- + +자바스크립트는 넷스케이프의 브렌던 아이크(Brendan Eich)가 1995년에 만들었습니다. +원래 자바스크립트는 웹사이트를 위한 단순한 스크립트 언어를 목표로 만들어졌는데, +좀 더 복잡한 웹 애플리케이션을 만들기 위해 자바를 보완하는 역할이었지만 +웹 페이지와의 긴밀한 상호작용과 브라우저에 대한 지원 기능 덕분에 웹 프론트엔드에서 +자바보다 훨씬 더 보편적으로 쓰이게 됐습니다. + +그렇지만 자바스크립트는 웹 브라우저에만 국한되지 않습니다. 구글 크롬의 V8 자바스크립트 +엔진을 위한 독립형 런타임을 제공하는 Node.js는 점점 인기를 얻고 있습니다. + +피드백 주시면 대단히 감사하겠습니다! [@adambrenecki](https://twitter.com/adambrenecki)나 +[adam@brenecki.id.au](mailto:adam@brenecki.id.au)를 통해 저와 만나실 수 있습니다. + +```js +// 주석은 C와 비슷합니다. 한 줄짜리 주석은 두 개의 슬래시로 시작하고, +/* 여러 줄 주석은 슬래시 별표로 시작해서 + 별표 슬래시로 끝납니다. */ + +// 구문은 세미콜론(;)으로 끝낼 수 있습니다. +doStuff(); + +// 하지만 꼭 그럴 필요는 없는데, 특정 경우를 제외하고 +// 새 줄이 시작할 때마다 세미콜론이 자동으로 삽입되기 때문입니다. +doStuff() + +// 여기서는 세미콜론을 생략하겠습니다. 세미콜론을 생략할지 여부는 +// 개인적인 취향이나 프로젝트의 스타일 가이드를 따릅니다. + +/////////////////////////////////// +// 1. 숫자, 문자열, 연산자 + +// 자바스크립트에는 단 하나의 숫자 타입(64비트 IEEE 754 배정도 숫자)만이 +// 있습니다. +3 // = 3 +1.5 // = 1.5 + +// 모든 기초 산술 연산은 기대한 대로 동작합니다. +1 + 1 // = 2 +8 - 1 // = 7 +10 * 2 // = 20 +35 / 5 // = 7 + +// 나누어 떨어지지 않는 나눗셈도 포함됩니다. +5 / 2 // = 2.5 + +// 비트 연산도 지원됩니다. float을 대상으로 비트 연산을 수행하면 +// 32비트까지 부호가 있는 int로 변환됩니다. +1 << 2 // = 4 + +// 괄호를 이용하면 우선순위를 지정할 수 있습니다. +(1 + 3) * 2 // = 8 + +// 실제 숫자가 아닌 특별한 세 가지 값이 있습니다. +Infinity // 1/0 1/0과 같은 연산의 결과 +-Infinity // -1/0과 같은 연산의 결과 +NaN // 0/0과 같은 연산의 결과 + +// 불린 타입도 있습니다. +true +false + +// 문자열은 '나 "로 생성합니다. +'abc' +"Hello, world" + +// 부정 연산에는 ! 기호를 이용합니다. +!true // = false +!false // = true + +// 동일성 연산은 == +1 == 1 // = true +2 == 1 // = false + +// 불일치 연산은 != +1 != 1 // = false +2 != 1 // = true + +// 그 밖의 비교 연산 +1 < 10 // = true +1 > 10 // = false +2 <= 2 // = true +2 >= 2 // = true + +// 문자열은 +로 연결할 수 있습니다. +"Hello " + "world!" // = "Hello world!" + +// 그리고 <와 >로 비교할 수 있습니다. +"a" < "b" // = true + +// 비교 시 타입 강제변환이 수행됩니다. +"5" == 5 // = true + +// ===를 쓰지 않는다면 말이죠. +"5" === 5 // = false + +// charAt을 이용하면 문자열 내의 문자에 접근할 수 있습니다. +"This is a string".charAt(0) + +// null과 undefined도 있습니다. +null // 의도적으로 값이 아님을 나타내는 데 사용합니다. +undefined // 값이 아직 설정되지 않음을 나타내는 데 사용합니다. + +// null, undefinded, NaN, 0, ""은 거짓이며, 그 밖의 다른 모든 값은 참입니다. +// 참고로 0은 거짓이며, "0"은 참입니다(심지어 0 == "0"이더라도). + +/////////////////////////////////// +// 2. 변수, 배열, 객체 + +// 변수는 var 키워드로 선언합니다. 자바스크립트는 동적 타입 언어라서 +// 타입을 지정할 필요가 없습니다. 값을 할당할 때는 = 문자 하나를 사용합니다. +var someVar = 5 + +// var 키워드를 지정하지 않아도 오류는 발생하지 않습니다. +someOtherVar = 10 + +// 그렇지만 변수가 여러분이 정의한 유효범위가 아니라 +// 전역 유효범위에 생성됩니다. + +// 값을 할당하지 않은 채로 선언한 변수는 undefined로 설정됩니다. +var someThirdVar // = undefined + +// 변수에 수학 연산을 수행하는 축약형 표현은 다음과 같습니다. +someVar += 5 // someVar = someVar + 5;와 같음. 이제 someVar는 10. +someVar *= 10 // somVar는 100 + +// 1을 더하거나 빼는 훨씬 더 짧은 표현도 있습니다. +someVar++ // 이제 someVar는 101 +someVar-- // 다시 100으로 되돌아감 + +// 배열은 순차적인 임의 타입 값의 목록입니다. +var myArray = ["Hello", 45, true] + +// 배열의 멤버는 대괄호로 둘러싼 인덱스를 이용해 접근할 수 있습니다. +// 배열의 인덱스는 0부터 시작합니다. +myArray[1] // = 45 + +// 자바스크립트의 객체는 다른 언어의 '사전'이나 '맵'과 같습니다. +// 즉, 키-값 쌍으로 구성된 비순차 컬렉션입니다. +{key1: "Hello", key2: "World"} + +// 키는 문자열이지만 유효한 자바스크립트 식별자일 경우 +// 작은따옴표는 필요하지 않습니다. 값은 어떤 타입이든 사용할 수 있습니다. +var myObj = {myKey: "myValue", "my other key": 4} + +// 객체 속성에도 인덱스를 이용해 접근할 수 있습니다. +myObj["my other key"] // = 4 + +// 또는 키가 유효한 식별자일 경우 점 표기법을 이용해 접근할 수 있습니다. +myObj.myKey // = "myValue" + +// 객체는 변경 가능합니다. 즉, 값을 변경하거나 새 키를 추가할 수 있습니다. +myObj.myThirdKey = true + +// 설정되지 않은 값에 접근하려고 하면 undefined가 반환됩니다. +myObj.myFourthKey // = undefined + +/////////////////////////////////// +// 3. 로직과 제어 구조 + +// if 구조는 여러분이 예상한 대로 동작합니다. +var count = 1 +if (count == 3){ + // count가 3일 경우 평가됨 +} else if (count == 4) { + // count가 4일 경우 평가됨 +} else { + // count가 3이나 4가 아닌 경우에 평가됨 +} + +// while도 마찬가지입니다. +while (true) { + // 무한 루프! +} + +// do-while 문은 항상 최소 한 번은 실행된다는 점을 제외하면 +// while 문과 비슷합니다. +var input +do { + input = getInput() +} while (!isValid(input)) + +// for 문은 C와 자바의 for 문과 같습니다. +// 초기화식; 지속 조건; 증감식 +for (var i = 0; i < 5; i++){ + // 5번 실행됨 +} + +// &&는 논리 and이고 ||는 논리 or입니다. +if (house.size == "big" && house.colour == "blue"){ + house.contains = "bear" +} +if (colour == "red" || colour == "blue"){ + // 색은 빨강이거나 파랑 +} + +// &&와 ||은 "단축 평가"를 수행하는데, 기본값을 설정할 때 유용합니다. +var name = otherName || "default" + +/////////////////////////////////// +// 4. 함수, 유효범위, 클로저 + +// 자바스크립트 함수는 function 키워드로 선언합니다. +function myFunction(thing){ + return thing.toUpperCase() +} +myFunction("foo") // = "FOO" + +// 함수는 "익명"으로, 즉 이름 없이 정의할 수도 있습니다. +function(thing){ + return thing.toLowerCase() +} +// (함수를 가리키는 이름이 없기 때문에 함수를 호출할 수 없습니다) + +// 자바스크립트 함수는 일급 객체이므로 다른 변수에 재할당하고 +// 다른 함수에 인자로 전달할 수 있습니다. 가령, 이벤트 핸들러를 만들 경우 +function myFunction(){ + // 이 코드는 5초 내에 호출됨 +} +setTimeout(myFunction, 5000) + +// 다른 함수를 호출할 때 직접적으로 함수 구문을 작성할 수도 있습니다. + +setTimeout(function myFunction(){ + // 이 코드는 5초 내에 호출됨 +}, 5000) + +// 자바스크립트에는 함수 유효범위가 있습니다. +// 함수는 자체적인 유효범위를 가지지만 다른 블록은 유효범위를 가지지 않습니다. +if (true){ + var i = 5 +} +i // = 5 - 블록 유효범위를 지원하는 언어에서는 undefined가 아닙니다. + +// 이것은 "즉시 실행되는 익명 함수"라는 공통 패턴으로 이어지는데, +// 이 패턴은 임시 변수가 전역 유효범위로 유출되는 것을 방지합니다. +(function(){ + var temporary = 5 + // '전역 객체'에 할당하는 식으로 전역 유효범위에 접근할 수 있는데, + // 브라우저에서 전역 객체는 항상 'window'입니다. 전역 객체는 + // Node.js와 같은 브라우저가 아닌 환경에서는 다른 이름일 수도 있습니다. + window.permanent = 10 + // 또는 앞에서 언급했다시피 var 키워드를 뺄 수도 있습니다. + permanent2 = 15 +})() +temporary // ReferenceError 발생 +permanent // = 10 +permanent2 // = 15 + +// 자바스크립트의 강력한 기능 중 하나는 클로저(closure)입니다. +// 함수가 다른 함수 안에서 정의되면 안쪽에 정의된 함수는 바깥 함수의 +// 모든 변수에 접근할 수 있습니다. +function sayHelloInFiveSeconds(name){ + var prompt = "Hello, " + name + "!" + function inner(){ + alert(prompt) + } + setTimeout(inner, 5000) + // setTimeout은 비동기적으로 동작하므로 이 함수는 5초 동안 + // 기다리지 않고 실행을 마칩니다. 하지만 5초가 지나면 inner에서도 + // prompt의 값에 접근할 수 있습니다. +} +sayHelloInFiveSeconds("Adam") // 5초 내로 "Hello, Adam!"이라고 적힌 팝업이 표시됨 + +/////////////////////////////////// +// 5. 객체 심화; 생성자와 프로토타입 + +// 객체는 함수를 포함할 수 있습니다. +var myObj = { + myFunc: function(){ + return "Hello world!" + } +} +myObj.myFunc() // = "Hello world!" + +// 객체에 포함된 함수가 호출되면 함수에서는 this 키워드를 이용해 +// 해당 함수가 포함된 객체에 접근할 수 있습니다. +myObj = { + myString: "Hello world!", + myFunc: function(){ + return this.myString + } +} +myObj.myFunc() // = "Hello world!" + +// 여기서 설정한 것은 함수가 정의된 곳이 아닌 함수가 호출되는 +// 방식과 관련이 있습니다. 그래서 아래 함수는 객체 컨텍스트에서 +// 호출되지 않으면 동작하지 않습니다. +var myFunc = myObj.myFunc +myFunc() // = undefined + +// 반대로 함수는 객체에 할당하고 this를 통해 해당 객체에 접근할 수 있습니다. +// 함수를 정의할 때 객체에 추가되지 않았더라도 마찬가지입니다. +var myOtherFunc = function(){ + return this.myString.toUpperCase() +} +myObj.myOtherFunc = myOtherFunc +myObj.myOtherFunc() // = "HELLO WORLD!" + +// new 키워드로 함수를 호출하면 새로운 객체가 생성되고 this를 통해 +// 함수에서 사용할 수 있게 됩니다. 이런 식으로 설계된 함수를 생성자라 합니다. + +var MyConstructor = function(){ + this.myNumber = 5 +} +myNewObj = new MyConstructor() // = {myNumber: 5} +myNewObj.myNumber // = 5 + +// 모든 자바스크립트 객체는 'prototype'을 가지고 있습니다. 어떤 객체에 대해 +// 실제 객체에는 존재하지 않는 프로퍼티에 접근하면 인터프리터는 프로로타입에서 +// 해당 프로퍼티를 찾습니다. + +// 일부 자바스크립트 구현체에서는 __proto__라는 마법의 프로퍼티로 +// 객체의 프로토타입에 접근하는 것을 허용하기도 합니다. 프로토타입을 +// 설명하기에는 이런 내용도 도움되겠지만 __proto__는 표준에 포함돼 +// 있지 않습니다. 나중에 프로토타입을 사용하는 표준 방법을 살펴보겠습니다. +var myObj = { + myString: "Hello world!", +} +var myPrototype = { + meaningOfLife: 42, + myFunc: function(){ + return this.myString.toLowerCase() + } +} +myObj.__proto__ = myPrototype +myObj.meaningOfLife // = 42 + +// 이 방법은 함수에도 통합니다. +myObj.myFunc() // = "hello world!" + +// 물론 프로퍼티가 프로토타입에 존재하지 않으면 +// 프로토타입의 프로토타입을 찾는 식으로 진행됩니다. +myPrototype.__proto__ = { + myBoolean: true +} +myObj.myBoolean // = true + +// 여기서 복사는 일어나지 않습니다. 각 객체에는 프로토타입에 대한 +// 참조가 보관돼 있습니다. 이는 프로토타입을 변경하면 변경사항이 +// 모든 곳에 반영된다는 의미입니다. +myPrototype.meaningOfLife = 43 +myObj.meaningOfLife // = 43 + +// 앞에서 __proto__가 표준에 포함돼 있지 않다고 이야기했는데, +// 기존 객체의 프로토타입을 변경하는 표준 방법은 없습니다. +// 하지만 특정 프로토타입을 가지고 새로운 객체를 생성하는 두 가지 +// 방법이 있습니다. + +// 첫 번째 방법은 Object.create를 이용하는 것인데, +// Object.create는 최근에 자바스크립트에 추가된 것이라서 아직까지 +// 모든 구현체에서 이용할 수 있는 것은 아닙니다. +var myObj = Object.create(myPrototype) +myObj.meaningOfLife // = 43 + +// 두 번째 방법은 어디서나 통하는 방법인데, 생성자와 관련이 있습니다. +// 생성자에는 prototype이라는 프로퍼티가 있습니다. 이 프로퍼티는 +// 생성자 함수 자체의 프로토타입이 *아니고* 생성자와 new 키워드를 이용해 +// 객체가 생성될 때 새로운 객체가 받는 프로토타입입니다. +myConstructor.prototype = { + getMyNumber: function(){ + return this.myNumber + } +} +var myNewObj2 = new myConstructor() +myNewObj2.getMyNumber() // = 5 + +// 문자열과 숫자와 같은 내장 타입에도 동등한 래퍼 객체를 +// 생성하는 생성자가 있습니다. +var myNumber = 12 +var myNumberObj = new Number(12) +myNumber == myNumberObj // = true + +// 하지만 정확히 같지는 않습니다. +typeof(myNumber) // = 'number' +typeof(myNumberObj) // = 'object' +myNumber === myNumberObj // = false +if (0){ + // 0은 거짓이라서 이 코드는 실행되지 않습니다. +} +if (Number(0)){ + // Number(0)은 참이라서 이 코드는 *실행됩니다*. +} + +// 하지만 래퍼 객체와 일반 내장 함수는 프로토타입을 공유하기 때문에 +// 가령 문자열에 실제로 기능을 추가할 수 있습니다. +String.prototype.firstCharacter = function(){ + return this.charAt(0) +} +"abc".firstCharacter() // = "a" + +// 이러한 사실은 기존 자바스크립트 버전에서 자바스크립트의 +// 새로운 기능을 구현하는 "폴리필(polyfilling)"에 자주 이용되므로 +// 오래된 버전의 브라우저와 같이 기존 환경에서 사용될 수 있습니다. + +// 예를 들어, Object.create가 모든 구현체에서 사용 가능한 것은 아니라고 +// 했지만 아래의 폴리필을 이용해 Object.create를 여전히 사용할 수 있습니다. +if (Object.create === undefined){ // 이미 존재하면 덮어쓰지 않음 + Object.create = function(proto){ + // 올바른 프로토타입을 가지고 임시 생성자를 만듬 + var Constructor = function(){} + Constructor.prototype = proto + // 그런 다음 임시 생성자를 이용해 새로운 적절한 프로토타입을 + // 포함한 객체를 생성 + return new Constructor() + } +} +``` + +## 기타 참고 자료 + +[모질라 개발자 네트워크](https://developer.mozilla.org/en-US/docs/Web/JavaScript)에서는 +자바스크립트에 대한 훌륭한 문서를 제공합니다. 더불어 위키 형식이라서 좀 더 많은 사항을 +배우게 되면 여러분만의 지식을 공유함으로써 다른 사람들에게 도움을 줄 수도 있습니다. + +MDN의 ['자바스크립트 재입문'](https://developer.mozilla.org/ko/docs/A_re-introduction_to_JavaScript)에서는 +여기서 다룬 개념의 상당수를 더욱 자세히 다루고 있습니다. 이 자료에서는 자바스크립트 언어 자체에 +대해서만 상당히 신중하게 다뤘습니다. 웹 페이지에서 자바스크립트를 사용하는 방법을 배우고 싶다면 +[문서 객체 모델(Document Object Model)](https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core)에 +관해 배우는 것으로 시작하길 바랍니다. + +[자바스크립트 가든](http://bonsaiden.github.io/JavaScript-Garden/)에서는 자바스크립트 언어에서 +직관에 어긋나는 모든 부분들을 심도 있게 다룹니다. + +더불어 이 글에 직접적으로 기여한 분들로, 내용 중 일부는 이 사이트에 있는 +루이 딘(Louie Dihn)의 파이썬 튜토리얼과 모질라 개발자 네트워크에 있는 +[자바스크립트 튜토리얼](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript)을 참고했습니다. diff --git a/ko-kr/lua-kr.html.markdown b/ko-kr/lua-kr.html.markdown new file mode 100644 index 00000000..04d119c4 --- /dev/null +++ b/ko-kr/lua-kr.html.markdown @@ -0,0 +1,424 @@ +--- +language: lua +category: language +contributors: + - ["Tyler Neylon", "http://tylerneylon.com/"] +translators: + - ["wikibook", "http://wikibook.co.kr"] +lang: ko-kr +--- + +```lua +-- 대시 두 개는 한 줄짜리 주석을 의미합니다. + +--[[ + [와 ]를 두 개씩 추가하면 여러 줄 주석이 됩니다. +--]] + +---------------------------------------------------- +-- 1. 변수와 흐름 제어 +---------------------------------------------------- + +num = 42 -- 모든 숫자는 double입니다. +-- 놀랄 필요는 없습니다. 64비트 double은 +-- 정확한 int 값을 저장하기 위해 52비트로 구성돼 +-- 있습니다. 52비트 이하의 int 값에 대해서는 +-- 장비 정밀도와 관련된 문제가 생기지 않습니다. + +s = 'walternate' -- 파이썬과 같은 불변 문자열 +t = "큰따옴표를 써도 됩니다" +u = [[ 이중 대괄호는 + 여러 줄 문자열을 + 나타냅니다.]] +t = nil -- 미정의 t. 루아는 가비지 컬렉션을 지원합니다. + +-- 블록은 do/end와 같은 키워드로 나타냅니다: +while num < 50 do + num = num + 1 -- ++나 += 유형의 연산자는 쓸 수 없습니다. +end + +-- If 절: +if num > 40 then + print('40 이상') +elseif s ~= 'walternate' then -- ~=은 '같지 않다'입니다. + -- 동일성 검사는 파이썬과 마찬가지로 ==입니다. + -- 문자열에도 쓸 수 있습니다. + io.write('not over 40\n') -- 기본적으로 stdout에 씁니다. +else + -- 변수는 기본적으로 전역 변수입니다. + thisIsGlobal = 5 -- 낙타 표기법이 일반적입니다. + + -- 변수를 지역 변수로 만드는 방법은 다음과 같습니다: + local line = io.read() -- 다음 stdin 줄을 읽습니다 + + -- 문자열 연결에는 .. 연산자를 씁니다: + print('겨울이 오고 있습니다, ' .. line) +end + +-- 미정의 변수는 nil을 반환합니다. +-- 다음 코드를 실행해도 오류가 나지 않습니다: +foo = anUnknownVariable -- 이제 foo는 nil입니다. + +aBoolValue = false + +-- nil과 false만이 거짓값입니다; 0과 ''은 참입니다! +if not aBoolValue then print('twas false') end + +-- 'or'와 'and'는 단축 평가(short-circuit)됩니다. +-- 다음 코드는 C/자바스크립트의 a?b:c 연산자와 비슷합니다: +ans = aBoolValue and 'yes' or 'no' --> 'no' + +karlSum = 0 +for i = 1, 100 do -- 범위에는 마지막 요소도 포함됩니다. + karlSum = karlSum + i +end + +-- 카운트 다운을 할 때는 "100, 1, -1"을 범위로 씁니다. +fredSum = 0 +for j = 100, 1, -1 do fredSum = fredSum + j end + +-- 일반적으로 범위는 begin, end[, step]입니다. + +-- 또 다른 반복문 구문은 다음과 같습니다: +repeat + print('미래의 방식') + num = num - 1 +until num == 0 + + +---------------------------------------------------- +-- 2. 함수 +---------------------------------------------------- + +function fib(n) + if n < 2 then return n end + return fib(n - 2) + fib(n - 1) +end + +-- 클로저와 익명 함수도 사용할 수 있습니다: +function adder(x) + -- 반환된 함수는 adder가 호출될 때 생성되고 x의 + -- 값이 유지됩니다: + return function (y) return x + y end +end +a1 = adder(9) +a2 = adder(36) +print(a1(16)) --> 25 +print(a2(64)) --> 100 + +-- 반환문, 함수 호출, 할당문은 길이가 다른 +-- 값의 리스트에 대해서도 모두 동작합니다. +-- 리스트에 값이 더 적을 때는 nil이 할당/반환되고 +-- 리스트에 값이 더 많을 때는 나머지 값은 버려집니다. + +x, y, z = 1, 2, 3, 4 +-- 이제 x = 1, y = 2, z = 3이고 4는 버려집니다. + +function bar(a, b, c) + print(a, b, c) + return 4, 8, 15, 16, 23, 42 +end + +x, y = bar('zaphod') --> "zaphod nil nil"가 출력 +-- 이제 x = 4, y = 8이고 15~42의 값은 버려집니다. + +-- 함수는 일급 객체이고, 지역/전역 유효범위를 가질 +-- 수 있습니다. 아래의 두 함수는 같습니다: +function f(x) return x * x end +f = function (x) return x * x end + +-- 그리고 아래의 두 함수도 마찬가지입니다: +local function g(x) return math.sin(x) end +local g; g = function (x) return math.sin(x) end +-- 'local g'라고 선언하면 g를 지역 함수로 만듭니다. + +-- 그나저나 삼각 함수는 라디안 단위로 동작합니다. + +-- 함수를 호출할 때 문자열 매개변수를 하나만 전달한다면 +-- 괄호를 쓰지 않아도 됩니다: +print 'hello' -- 잘 동작합니다. + + +---------------------------------------------------- +-- 3. 테이블 +---------------------------------------------------- + +-- 테이블 = 루아의 유일한 복합 자료구조로서, 연관 배열입니다. +-- PHP의 배열이나 자바스크립트의 객체와 비슷하며, +-- 리스트로도 사용할 수 있는 해시 기반의 딕셔너리입니다. + +-- 테이블을 딕셔너리/맵으로 사용하기: + +-- 딕셔너리 리터럴은 기본적으로 문자열 키를 가집니다: +t = {key1 = 'value1', key2 = false} + +-- 문자열 키에는 자바스크립트와 유사한 점 표기법을 쓸 수 있습니다: +print(t.key1) -- 'value1'을 출력. +t.newKey = {} -- 새 키/값 쌍을 추가. +t.key2 = nil -- 테이블에서 key2를 제거. + +-- (nil이 아닌) 값을 키로 사용하는 리터럴 표기법: +u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} +print(u[6.28]) -- "tau"가 출력 + +-- 키 매칭은 기본적으로 숫자와 문자열에 대해서는 값으로 하지만 +-- 테이블에 대해서는 식별자로 합니다. +a = u['@!#'] -- Now a = 'qbert'. +b = u[{}] -- We might expect 1729, but it's nil: +a = u['@!#'] -- 이제 a는 'qbert'입니다. +b = u[{}] -- 1729를 예상했겠지만 nil입니다: +-- 탐색이 실패하기 때문에 b는 nil입니다. 탐색이 실패하는 이유는 +-- 사용된 키가 원본 값을 저장할 때 사용한 키와 동일한 객체가 아니기 +-- 때문입니다. 따라서 문자열 및 숫자가 좀 더 이식성 있는 키입니다. + +-- 테이블 하나를 매개변수로 취하는 함수를 호출할 때는 괄호가 필요하지 않습니다: +function h(x) print(x.key1) end +h{key1 = 'Sonmi~451'} -- 'Sonmi~451'를 출력. + +for key, val in pairs(u) do -- 테이블 순회 + print(key, val) +end + +-- _G는 모든 전역 멤버에 대한 특별한 테이블입니다. +print(_G['_G'] == _G) -- 'true'가 출력 + +-- 테이블을 리스트/배열로 사용하기: + +-- 리스트 리터럴은 암묵적으로 int 키로 설정됩니다: +v = {'value1', 'value2', 1.21, 'gigawatts'} +for i = 1, #v do -- #v는 리스트 v의 크기입니다. + print(v[i]) -- 인덱스가 1에서 시작합니다!! 제정신이 아닙니다! +end +-- 'list'는 실제 타입이 아닙니다. v는 연속된 정수형 키가 포함된 +-- 테이블이고 리스트로 취급될 뿐입니다. + +---------------------------------------------------- +-- 3.1 메타테이블과 메타메서드 +---------------------------------------------------- + +-- 테이블은 테이블에 연산자 오버로딩을 가능하게 하는 메타테이블을 +-- 가질 수 있습니다. 나중에 메타테이블이 어떻게 자바스크립트 +-- 프로토타입과 같은 행위를 지원하는지 살펴보겠습니다. + +f1 = {a = 1, b = 2} -- 분수 a/b를 표현 +f2 = {a = 2, b = 3} + +-- 다음 코드는 실패합니다: +-- s = f1 + f2 + +metafraction = {} +function metafraction.__add(f1, f2) + sum = {} + sum.b = f1.b * f2.b + sum.a = f1.a * f2.b + f2.a * f1.b + return sum +end + +setmetatable(f1, metafraction) +setmetatable(f2, metafraction) + +s = f1 + f2 -- f1의 메타테이블을 대상으로 __add(f1, f2)를 호출 + +-- f1과 f2는 자바스크립트의 프로토타입과 달리 각 메타테이블에 대한 +-- 키가 없어서 getmetatable(f1)과 같이 받아와야 합니다. +-- 메타테이블은 __add 같은 루아가 알고 있는 키가 지정된 일반 테이블입니다. + +-- 그렇지만 다음 줄은 s가 메타테이블을 가지고 있지 않기 때문에 실패합니다. +-- t = s + s +-- 아래와 같이 클래스와 유사한 패턴은 이러한 문제가 발생하지 않습니다. + +-- 메타테이블에 대한 __index는 점을 이용한 탐색을 오버로드합니다: +defaultFavs = {animal = 'gru', food = 'donuts'} +myFavs = {food = 'pizza'} +setmetatable(myFavs, {__index = defaultFavs}) +eatenBy = myFavs.animal -- 동작합니다! 고마워요, 메타테이블! + +-- 직접적인 메타테이블 탐색이 실패할 경우 메타테이블의 __index 값을 이용해 +-- 재시도하고, 이런 과정이 반복됩니다. + +-- __index 값은 좀 더 세분화된 탐색을 위해 function(tbl, key)가 +-- 될 수도 있습니다. + +-- __index, __add, ...의 값을 메타메서드라고 합니다. +-- 다음은 메타메서드를 가진 테이블의 전체 목록입니다. + +-- __add(a, b) for a + b +-- __sub(a, b) for a - b +-- __mul(a, b) for a * b +-- __div(a, b) for a / b +-- __mod(a, b) for a % b +-- __pow(a, b) for a ^ b +-- __unm(a) for -a +-- __concat(a, b) for a .. b +-- __len(a) for #a +-- __eq(a, b) for a == b +-- __lt(a, b) for a < b +-- __le(a, b) for a <= b +-- __index(a, b) <fn이나 테이블> for a.b +-- __newindex(a, b, c) for a.b = c +-- __call(a, ...) for a(...) + +---------------------------------------------------- +-- 3.2 클래스 형태의 테이블과 상속 +---------------------------------------------------- + +-- 루아에는 클래스가 내장돼 있지 않으며, 테이블과 메타테이블을 +-- 이용해 클래스를 만드는 다양한 방법이 있습니다. + +-- 다음 예제에 대한 설명은 하단을 참조합니다. + +Dog = {} -- 1. + +function Dog:new() -- 2. + newObj = {sound = 'woof'} -- 3. + self.__index = self -- 4. + return setmetatable(newObj, self) -- 5. +end + +function Dog:makeSound() -- 6. + print('I say ' .. self.sound) +end + +mrDog = Dog:new() -- 7. +mrDog:makeSound() -- 'I say woof' -- 8. + +-- 1. Dog는 클래스처럼 동작합니다. 실제로는 테이블입니다. +-- 2. function 테이블명:fn(...)은 +-- function 테이블명.fn(self, ...)과 같습니다. +-- :는 self라는 첫 번째 인자를 추가할 뿐입니다. +-- self가 값을 어떻게 얻는지 궁금하다면 아래의 7과 8을 읽어보세요. +-- 3. newObj는 Dog 클래스의 인스턴스가 됩니다. +-- 4. self = 인스턴스화되는 클래스. +-- 주로 self = Dog이지만 상속을 이용하면 이것을 바꿀 수 있습니다. +-- newObj의 메타테이블과 self의 __index를 모두 self에 설정하면 +-- newObj가 self의 함수를 갖게 됩니다. +-- 5. 참고: setmetatable은 첫 번째 인자를 반환합니다. +-- 6. :는 2에서 설명한 것과 같이 동작하지만 이번에는 self가 +-- 클래스가 아닌 인스턴스라고 예상할 수 있습니다. +-- 7. Dog.new(Dog)과 같으므로 new()에서는 self = Dog입니다. +-- 8. mrDog.makeSound(mrDog)과 같으므로 self = mrDog입니다. + +---------------------------------------------------- + +-- 상속 예제: + +LoudDog = Dog:new() -- 1. + +function LoudDog:makeSound() + s = self.sound .. ' ' -- 2. + print(s .. s .. s) +end + +seymour = LoudDog:new() -- 3. +seymour:makeSound() -- 'woof woof woof' -- 4. + +-- 1. LoudDog은 Dog의 메서드와 변수를 갖게 됩니다. +-- 2. self는 new()에서 'sound' 키를 가집니다. 3을 참고하세요. +-- 3. LoudDog.new(LoudDog)과 같고, LoudDog은 'new' 키가 없지만 +-- 메타테이블에서 __index = Dog이기 때문에 Dog.new(LoudDog)으로 +-- 변환됩니다. +-- 결과: seymour의 메타테이블은 LoudDog이고 LoudDog.__index는 +-- LoudDog입니다. 따라서 seymour.key는 seymour.key, +-- LoudDog.key, Dog.key와 같을 것이며, 지정한 키에 어떤 테이블이 +-- 오든 상관없을 것입니다. +-- 4. 'makeSound' 키는 LoudDog에서 발견할 수 있습니다. +-- 이것은 LoudDog.makeSound(seymour)와 같습니다. + +-- 필요할 경우, 하위 클래스의 new()는 기반 클래스의 new()와 유사합니다. +function LoudDog:new() + newObj = {} + -- newObj를 구성 + self.__index = self + return setmetatable(newObj, self) +end + +---------------------------------------------------- +-- 4. 모듈 +---------------------------------------------------- + + +--[[ 여기서 주석을 제거하면 이 스크립트의 나머지 부분은 +-- 실행 가능한 상태가 됩니다. +``` + +```lua +-- mod.lua 파일의 내용이 다음과 같다고 가정해 봅시다. +local M = {} + +local function sayMyName() + print('이소룡') +end + +function M.sayHello() + print('안녕하세요') + sayMyName() +end + +return M + +-- 또 다른 파일에서는 mod.lua의 기능을 이용할 수 있습니다. +local mod = require('mod') -- mod.lua 파일을 실행 + +-- require는 모듈을 포함시키는 표준화된 방법입니다. +-- require는 다음과 같이 동작합니다: (캐싱돼 있지 않을 경우. 하단 참조) +local mod = (function () + <mod.lua의 내용> +end)() +-- mod.lua가 함수의 본문처럼 되므로 mod.lua 안의 지역 멤버는 +-- 밖에서 볼 수 없습니다. + +-- 다음 코드가 동작하는 것은 mod가 mod.lua의 M과 같기 때문입니다. +mod.sayHello() -- 이소룡 씨에게 인사를 건넵니다. + +-- 다음 코드를 실행하면 오류가 발생합니다. +-- sayMyName는 mod.lua 안에서만 존재하기 때문입니다: +mod.sayMyName() -- 오류 + +-- require의 반환값은 캐싱되므로 require를 여러 번 실행해도 +-- 파일은 최대 한 번만 실행됩니다. + +-- mod2.lua에 "print('Hi')"가 들어 있다고 가정해 봅시다. +local a = require('mod2') -- Hi!를 출력 +local b = require('mod2') -- print를 실행하지 않음. a=b + +-- dofile은 require와 비슷하지만 캐싱을 하지 않습니다: +dofile('mod2') --> Hi! +dofile('mod2') --> Hi! (require와 달리 다시 한번 실행됨) + +-- loadfile은 루아 파일을 읽어들이지만 실행하지는 않습니다 +f = loadfile('mod2') -- f()를 호출해야 mod2.lua가 실행됩니다. + +-- loadstring은 문자열에 대한 loadfile입니다. +g = loadstring('print(343)') -- 함수를 반환합니다. +g() -- 343이 출력됩니다. 그전까지는 아무것도 출력되지 않습니다. + +--]] + +``` + +## 참고자료 + +루아를 배우는 일이 흥미진진했던 이유는 <a href="http://love2d.org/">Love 2D 게임 엔진</a>을 이용해 +게임을 만들 수 있었기 때문입니다. 이것이 제가 루아를 배운 이유입니다. + +저는 <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">BlackBulletIV의 "프로그래머를 위한 루아"</a>로 +시작했습니다. 그다음으로 공식 <a href="http://www.lua.org/pil/contents.html">"프로그래밍 루아"</a> 책을 읽었습니다. +그렇게 루아를 배웠습니다. + +lua-users.org에 있는 <a href="http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">짧은 루아 레퍼런스</a>를 +읽어두면 도움될지도 모르겠습니다. + +여기서는 표준 라이브러리에 관해서는 다루지 않았습니다. + +* <a href="http://lua-users.org/wiki/StringLibraryTutorial">string 라이브러리</a> +* <a href="http://lua-users.org/wiki/TableLibraryTutorial">table 라이브러리</a> +* <a href="http://lua-users.org/wiki/MathLibraryTutorial">math 라이브러리</a> +* <a href="http://lua-users.org/wiki/IoLibraryTutorial">io 라이브러리</a> +* <a href="http://lua-users.org/wiki/OsLibraryTutorial">os 라이브러리</a> + +그나저나 이 파일 전체는 유효한 루아 프로그램입니다. 이 파일을 +learn.lua로 저장한 후 "lua learn.lua"를 실행해 보세요! + +이 글은 tylerneylon.com에 처음으로 써본 글이며, +<a href="https://gist.github.com/tylerneylon/5853042">Github의 Gist</a>에서도 확인할 수 있습니다. +루아로 즐거운 시간을 보내세요! diff --git a/ko-kr/python-kr.html.markdown b/ko-kr/python-kr.html.markdown new file mode 100644 index 00000000..a131e9a2 --- /dev/null +++ b/ko-kr/python-kr.html.markdown @@ -0,0 +1,484 @@ +--- +language: python +category: language +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +filename: learnpython.py +translators: + - ["wikibook", "http://wikibook.co.kr"] +lang: ko-kr +--- + +파이썬은 귀도 반 로섬이 90년대에 만들었습니다. 파이썬은 현존하는 널리 사용되는 언어 중 하나입니다. +저는 문법적 명료함에 반해 파이썬을 사랑하게 됐습니다. 파이썬은 기본적으로 실행 가능한 의사코드입니다. + +피드백 주시면 정말 감사하겠습니다! [@louiedinh](http://twitter.com/louiedinh)나 +louiedinh [at] [구글의 이메일 서비스]를 통해 저에게 연락하시면 됩니다. + +참고: 이 글은 구체적으로 파이썬 2.7에 해당하는 내용을 담고 있습니다만 +파이썬 2.x에도 적용할 수 있을 것입니다. 파이썬 3을 다룬 튜토리얼도 곧 나올 테니 기대하세요! + +```python +# 한 줄짜리 주석은 해시로 시작합니다. +""" 여러 줄 문자열은 "를 세 개 써서 시작할 수 있고, + 주석으로 자주 사용됩니다. +""" + +#################################################### +## 1. 기본 자료형과 연산자 +#################################################### + +# 숫자 +3 #=> 3 + +# 수학 연산은 예상하신 대로입니다. +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# 나눗셈은 약간 까다롭습니다. 정수로 나눈 다음 결과값을 자동으로 내림합니다. +5 / 2 #=> 2 + +# 나눗셈 문제를 해결하려면 float에 대해 알아야 합니다. +2.0 # 이것이 float입니다. +11.0 / 4.0 #=> 2.75 훨씬 낫네요 + +# 괄호를 이용해 연산자 우선순위를 지정합니다. +(1 + 3) * 2 #=> 8 + +# 불린(Boolean) 값은 기본형입니다. +True +False + +# not을 이용해 부정합니다. +not True #=> False +not False #=> True + +# 동일성 연산자는 ==입니다. +1 == 1 #=> True +2 == 1 #=> False + +# 불일치 연산자는 !=입니다. +1 != 1 #=> False +2 != 1 #=> True + +# 그밖의 비교 연산자는 다음과 같습니다. +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# 비교 연산을 연결할 수도 있습니다! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# 문자열은 "나 '로 생성합니다. +"This is a string." +'This is also a string.' + +# 문자열도 연결할 수 있습니다! +"Hello " + "world!" #=> "Hello world!" + +# 문자열은 문자로 구성된 리스트로 간주할 수 있습니다. +"This is a string"[0] #=> 'T' + +# %는 다음과 같이 문자열을 형식화하는 데 사용할 수 있습니다: +"%s can be %s" % ("strings", "interpolated") + +# 문자열을 형식화하는 새로운 방법은 format 메서드를 이용하는 것입니다. +# 이 메서드를 이용하는 방법이 더 선호됩니다. +"{0} can be {1}".format("strings", "formatted") +# 자릿수를 세기 싫다면 키워드를 이용해도 됩니다. +"{name} wants to eat {food}".format(name="Bob", food="lasagna") + +# None은 객체입니다. +None #=> None + +# 객체와 None을 비교할 때는 동일성 연산자인 `==`를 사용해서는 안 됩니다. +# 대신 `is`를 사용하세요. +"etc" is None #=> False +None is None #=> True + +# 'is' 연산자는 객체의 식별자를 검사합니다. +# 기본형 값을 다룰 때는 이 연산자가 그다지 유용하지 않지만 +# 객체를 다룰 때는 매우 유용합니다. + +# None, 0, 빈 문자열/리스트는 모두 False로 평가됩니다. +# 그밖의 다른 값은 모두 True입니다 +0 == False #=> True +"" == False #=> True + + +#################################################### +## 2. 변수와 컬렉션 +#################################################### + +# 뭔가를 출력하는 것은 상당히 쉽습니다. +print "I'm Python. Nice to meet you!" + + +# 변수에 값을 할당하기 전에 변수를 반드시 선언하지 않아도 됩니다. +some_var = 5 # 명명관례는 '밑줄이_포함된_소문자'입니다. +some_var #=> 5 + +# 미할당된 변수에 접근하면 예외가 발생합니다. +# 예외 처리에 관해서는 '제어 흐름'을 참고하세요. +some_other_var # 이름 오류가 발생 + +# 표현식으로도 사용할 수 있습니다. +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# 리스트는 순차 항목을 저장합니다. +li = [] +# 미리 채워진 리스트로 시작할 수도 있습니다. +other_li = [4, 5, 6] + +# append를 이용해 리스트 끝에 항목을 추가합니다. +li.append(1) #li는 이제 [1]입니다. +li.append(2) #li는 이제 [1, 2]입니다. +li.append(4) #li는 이제 [1, 2, 4]입니다. +li.append(3) #li는 이제 [1, 2, 4, 3]입니다. +# pop을 이용해 끝에서부터 항목을 제거합니다. +li.pop() #=> 3이 반환되고 li는 이제 [1, 2, 4]입니다. +# 다시 넣어봅시다 +li.append(3) # li는 이제 다시 [1, 2, 4, 3]가 됩니다. + +# 배열에서 했던 것처럼 리스트에도 접근할 수 있습니다. +li[0] #=> 1 +# 마지막 요소를 봅시다. +li[-1] #=> 3 + +# 범위를 벗어나서 접근하면 IndexError가 발생합니다. +li[4] # IndexError가 발생 + +# 슬라이스 문법을 통해 범위를 지정해서 값을 조회할 수 있습니다. +# (이 문법을 통해 간편하게 범위를 지정할 수 있습니다.) +li[1:3] #=> [2, 4] +# 앞부분을 생략합니다. +li[2:] #=> [4, 3] +# 끝부분을 생략합니다. +li[:3] #=> [1, 2, 4] + +# del로 임의의 요소를 제거할 수 있습니다. +del li[2] # li is now [1, 2, 3] + +# 리스트를 추가할 수도 있습니다. +li + other_li #=> [1, 2, 3, 4, 5, 6] - 참고: li와 other_li는 그대로 유지됩니다. + +# extend로 리스트를 연결합니다. +li.extend(other_li) # 이제 li는 [1, 2, 3, 4, 5, 6]입니다. + +# in으로 리스트 안에서 특정 요소가 존재하는지 확인합니다. +1 in li #=> True + +# len으로 길이를 검사합니다. +len(li) #=> 6 + +# 튜플은 리스트와 비슷하지만 불변성을 띱니다. +tup = (1, 2, 3) +tup[0] #=> 1 +tup[0] = 3 # TypeError가 발생 + +# 튜플에 대해서도 리스트에서 할 수 있는 일들을 모두 할 수 있습니다. +len(tup) #=> 3 +tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tup[:2] #=> (1, 2) +2 in tup #=> True + +# 튜플(또는 리스트)을 변수로 풀 수 있습니다. +a, b, c = (1, 2, 3) # 이제 a는 1, b는 2, c는 3입니다 +# 괄호를 빼면 기본적으로 튜플이 만들어집니다. +d, e, f = 4, 5, 6 +# 이제 두 값을 바꾸는 게 얼마나 쉬운지 확인해 보세요. +e, d = d, e # 이제 d는 5이고 e는 4입니다. + +# 딕셔너리는 매핑을 저장합니다. +empty_dict = {} +# 다음은 값을 미리 채운 딕셔너리입니다. +filled_dict = {"one": 1, "two": 2, "three": 3} + +# []를 이용해 값을 조회합니다. +filled_dict["one"] #=> 1 + +# 모든 키를 리스트로 구합니다. +filled_dict.keys() #=> ["three", "two", "one"] +# 참고 - 딕셔너리 키의 순서는 보장되지 않습니다. +# 따라서 결과가 이와 정확히 일치하지 않을 수도 있습니다. + +# 모든 값을 리스트로 구합니다. +filled_dict.values() #=> [3, 2, 1] +# 참고 - 키 순서와 관련해서 위에서 설명한 내용과 같습니다. + +# in으로 딕셔너리 안에 특정 키가 존재하는지 확인합니다. +"one" in filled_dict #=> True +1 in filled_dict #=> False + +# 존재하지 않는 키를 조회하면 KeyError가 발생합니다. +filled_dict["four"] # KeyError + +# get 메서드를 이용하면 KeyError가 발생하지 않습니다. +filled_dict.get("one") #=> 1 +filled_dict.get("four") #=> None +# get 메서드는 값이 누락된 경우 기본 인자를 지원합니다. +filled_dict.get("one", 4) #=> 1 +filled_dict.get("four", 4) #=> 4 + +# setdefault 메서드는 딕셔너리에 새 키-값 쌍을 추가하는 안전한 방법입니다. +filled_dict.setdefault("five", 5) #filled_dict["five"]는 5로 설정됩니다. +filled_dict.setdefault("five", 6) #filled_dict["five"]는 여전히 5입니다. + + +# 세트는 집합을 저장합니다. +empty_set = set() +# 다수의 값으로 세트를 초기화합니다. +some_set = set([1,2,2,3,4]) # 이제 some_set는 set([1, 2, 3, 4])입니다. + +# 파이썬 2.7부터는 {}를 세트를 선언하는 데 사용할 수 있습니다. +filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# 세트에 항목을 추가합니다. +filled_set.add(5) # 이제 filled_set는 {1, 2, 3, 4, 5}입니다. + +# &을 이용해 교집합을 만듭니다. +other_set = {3, 4, 5, 6} +filled_set & other_set #=> {3, 4, 5} + +# |를 이용해 합집합을 만듭니다. +filled_set | other_set #=> {1, 2, 3, 4, 5, 6} + +# -를 이용해 차집합을 만듭니다. +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# in으로 세트 안에 특정 요소가 존재하는지 검사합니다. +2 in filled_set #=> True +10 in filled_set #=> False + + +#################################################### +## 3. 제어 흐름 +#################################################### + +# 변수를 만들어 봅시다. +some_var = 5 + +# 다음은 if 문입니다. 파이썬에서는 들여쓰기가 대단히 중요합니다! +# 다음 코드를 실행하면 "some_var is smaller than 10"가 출력됩니다. +if some_var > 10: + print "some_var is totally bigger than 10." +elif some_var < 10: # elif 절은 선택사항입니다. + print "some_var is smaller than 10." +else: # 이 부분 역시 선택사항입니다. + print "some_var is indeed 10." + + +""" +for 루프는 리스트를 순회합니다. +아래 코드는 다음과 같은 내용을 출력합니다: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # %로 형식화된 문자열에 값을 채워넣을 수 있습니다. + print "%s is a mammal" % animal + +""" +`range(number)`는 숫자 리스트를 반환합니다. +이때 숫자 리스트의 범위는 0에서 지정한 숫자까지입니다. +아래 코드는 다음과 같은 내용을 출력합니다: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +while 루프는 조건이 더는 충족되지 않을 때까지 진행됩니다. +prints: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # x = x + 1의 축약형 + +# try/except 블록을 이용한 예외 처리 + +# 파이썬 2.6 및 상위 버전에서 동작하는 코드 +try: + # raise를 이용해 오류를 발생시킵니다 + raise IndexError("This is an index error") +except IndexError as e: + pass # pass는 단순 no-op 연산입니다. 보통 이곳에 복구 코드를 작성합니다. + + +#################################################### +## 4. 함수 +#################################################### + +# 새 함수를 만들 때 def를 사용합니다. +def add(x, y): + print "x is %s and y is %s" % (x, y) + return x + y # return 문을 이용해 값을 반환합니다. + +# 매개변수를 전달하면서 함수를 호출 +add(5, 6) #=> "x is 5 and y is 6"가 출력되고 11이 반환됨 + +# 함수를 호출하는 또 다른 방법은 키워드 인자를 지정하는 방법입니다. +add(y=6, x=5) # 키워드 인자는 순서에 구애받지 않습니다. + +# 위치 기반 인자를 임의 개수만큼 받는 함수를 정의할 수 있습니다. +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# 키워드 인자를 임의 개수만큼 받는 함수 또한 정의할 수 있습니다. +def keyword_args(**kwargs): + return kwargs + +# 이 함수를 호출해서 어떤 일이 일어나는지 확인해 봅시다. +keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} + +# 원한다면 한 번에 두 가지 종류의 인자를 모두 받는 함수를 정의할 수도 있습니다. +def all_the_args(*args, **kwargs): + print args + print kwargs +""" +all_the_args(1, 2, a=3, b=4)를 실행하면 다음과 같은 내용이 출력됩니다: + (1, 2) + {"a": 3, "b": 4} +""" + +# 함수를 호출할 때 varargs/kwargs와 반대되는 일을 할 수 있습니다! +# *를 이용해 튜플을 확장하고 **를 이용해 kwargs를 확장합니다. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # foo(1, 2, 3, 4)와 같음 +all_the_args(**kwargs) # foo(a=3, b=4)와 같음 +all_the_args(*args, **kwargs) # foo(1, 2, 3, 4, a=3, b=4)와 같음 + +# 파이썬에는 일급 함수가 있습니다 +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) #=> 13 + +# 게다가 익명 함수도 있습니다. +(lambda x: x > 2)(3) #=> True + +# 내장된 고차 함수(high order function)도 있습니다. +map(add_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] + +# 맵과 필터에 리스트 조건 제시법(list comprehensions)을 사용할 수 있습니다. +[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + +#################################################### +## 5. 클래스 +#################################################### + +# 클래스를 하나 만들기 위해 특정 객체의 하위 클래스를 만들 수 있습니다. +class Human(object): + + # 클래스 속성은 이 클래스의 모든 인스턴스에서 공유합니다. + species = "H. sapiens" + + # 기본 초기화자 + def __init__(self, name): + # 인자를 인스턴스의 name 속성에 할당합니다. + self.name = name + + # 모든 인스턴스 메서드에서는 self를 첫 번째 인자로 받습니다. + def say(self, msg): + return "%s: %s" % (self.name, msg) + + # 클래스 메서드는 모든 인스턴스에서 공유합니다. + # 클래스 메서드는 호출하는 클래스를 첫 번째 인자로 호출됩니다. + @classmethod + def get_species(cls): + return cls.species + + # 정적 메서드는 클래스나 인스턴스 참조 없이도 호출할 수 있습니다. + @staticmethod + def grunt(): + return "*grunt*" + + +# 클래스 인스턴스화 +i = Human(name="Ian") +print i.say("hi") # "Ian: hi"가 출력됨 + +j = Human("Joel") +print j.say("hello") # "Joel: hello"가 출력됨 + +# 클래스 메서드를 호출 +i.get_species() #=> "H. sapiens" + +# 공유 속성을 변경 +Human.species = "H. neanderthalensis" +i.get_species() #=> "H. neanderthalensis" +j.get_species() #=> "H. neanderthalensis" + +# 정적 메서드를 호출 +Human.grunt() #=> "*grunt*" + + +#################################################### +## 6. 모듈 +#################################################### + +# 다음과 같이 모듈을 임포트할 수 있습니다. +import math +print math.sqrt(16) #=> 4 + +# 모듈의 특정 함수를 호출할 수 있습니다. +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# 모듈의 모든 함수를 임포트할 수 있습니다. +# Warning: this is not recommended +from math import * + +# 모듈 이름을 축약해서 쓸 수 있습니다. +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# 파이썬 모듈은 평범한 파이썬 파일에 불과합니다. +# 직접 모듈을 작성해서 그것들을 임포트할 수 있습니다. +# 모듈의 이름은 파일의 이름과 같습니다. + +# 다음과 같은 코드로 모듈을 구성하는 함수와 속성을 확인할 수 있습니다. +import math +dir(math) + + +``` + +## 더 배울 준비가 되셨습니까? + +### 무료 온라인 참고자료 + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) + +### 파이썬 관련 도서 + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
\ No newline at end of file |