JavaScript의 Scope는 Block(블록 { } ) 이 아닌 Function(함수)에 의해 정해집니다.


우선 scope에 대한 간단한 예시 입니다. 


scope(유효범위) 란 ?


JavaScript 뿐만 아니라 모든 프로그래밍 언어에서도 통용되는 말이며


block Scope라 함은 

{

  변수 선언 

}

시 block 을 나가면 선언된 변수가 block 안에서만 생존 하는 것을 말합니다.

JavaScript는 기본적으로 block Scope가 아니라 Function Scope 입니다.

function a(){

변수 선언! (A)

    {  

     변수 선언 !(B) 

   }



// 변수 A와 B둘다 살아있음

}



이와 같이 변수를 선언해도 펑션안에서는 어떻게든 살아서 있기 때문에 접근도 가능합니다.

기본적인 block Scope는 C 언어를 보면 알수 있습니다.



블록 안에서 선언된 변수 들은 블록 안에서 끝나지 않고 Function(함수) 단위로 가게 됩니다.


그에 해당 하는 테스트 샘플 코드입니다.





function foo()
{
		console.warn('__Before__');	
		typeof first ==='number' ? console.log('first exist') : console.error('first not exist');
		typeof Internal==='function' ? Internal() : console.error('not exist');
		/*
			first not exist  'number'로 비교하였지만 undefined로 호이스팅(끌어올리다) 
			Internal exist   'function' 으로 비교하여 참조 의 호이스팅이 되는점 확인 -> 실제 함수 사용까지 가능)

		*/
		var first = 1;
		function Internal(){console.log("Internal exist");}

		console.warn('__after__');
		typeof first ==='number' ? console.log('first exist') : console.error('first not exist');
		typeof Internal==='function' ? Internal() : console.error('not exist');

		/*
			first exist 
			Internal exist 
		*/
		if(first===1){var third = 3;};

		typeof third==='number' ? console.log('third exist') : console.error('third not exist');
		
		/*
			third exist  var third 선언은 if(first===1) 분기를 타고 블록(block) 안에 선언되었지만 밖에서도 참조가 가능
		*/

}
foo();






Hoisting ?

코드 실행 전의 변수와 함수 선언을 해당 범위의 맨위로 이동 시키는 JavaScript 의 매커니즘 


고려해야 할 조건이 있습니다.


1. 변수 할당은 함수 선언보다 우선 

2. 함수 선언은 변수 선언보다 우선 

-> 하지만 함수 선언이 변수 할당을 넘어 서진 않습니다.



관련 참고 사이트 // 설명이 잘 되어있습니다. 

https://scotch.io/tutorials/understanding-hoisting-in-javascript






이런느낌으로 알고 지나가는게 좋을 것 같습니다.


펑션은 호이스팅으로 참조까지 가능하지만


변수(var)는 undefined로 호이스팅이 되는점









C언어는 절차 지향 언어라고 할수 있다. 해당 내용은 절차지향에 대한 이야기 일뿐


자바스크립트와는 많은 관련이 있진 않습니다. C를 하다 넘어 왔기 때문에


자바스크립트도 절차지향으로 보여 잘못생각하였던 부분에 대한 설명입니다.






#include 
using namespace std;


int main(void)
{
	printf("CPP Test\n");

	show(); //show 식별자를 찾을수 없습니다. 에러 
	return 0;
}

 void show() 
{
	printf("Show Call");
}

const int OpenResult(int flag) 
{


}



// 해당 호출이 불가능해지기 때문에


// 실제 사용시에는

// 이 처럼 코드 상단에 미리 선언을 하고 원형을 하단에 작성한다.C 의경우


#include 
using namespace std;

// 절차 선언 
void show();
int main(void)
{
	printf("CPP Test\n");

	show();
	return 0;
}

 void show() 
{
	printf("Show Call");
}


의 형태로 지원되어야 한다. 절차지향




자바스크립트 또한 그럴것이라 생각 하였지만 실제 JS에서 유효범위는 생각과는 달랐다.










function external(){

typeof Internal ==='function'  ?  console.log("Internal  exist") : console.log("Internal  not exist");

function Internal (){};

typeof Internal ==='function'  ?  console.log("Internal  exist") : console.log("Internal  not exist");

window.Internal === undefined ? console.log('Internal is not window exist' ) : console.log('Internal window exist');

window.external === undefined ? console.log('external is not window exist') : console.log('external window exist');
}

external();




결과


Internal  exist

Internal  exist

Internal is not window exist

external window exist



1번째에


typeof Internal ==='function 부분에서 exist로 넘어가는것으로 보아


절차적으로 코드가 생성되는것으로 보였지만 


자바스크립트의 유효범위는 블록이 아니라 함수에 의에 정의된다고 할수있다.


여기까지보면 뭔가 큰 차이가 안 느껴져서  자바스크립트의 Scope Chain 은 Function 이라는 예제를 하나 더 들수 있다.

C의 경우




void show() 
{
	printf("Show Call");

	for (int i = 0; i < 5; i++)
	{
		int b = 10;

	}
	printf("B is %d", b);
}

// 와 작성시 이미 printf b 에서 컴파일 하기도전에 validation 에 걸립니다. b가 정의되어있지 않습니다. 
// C,C++에서는 Scope Chain 은 Block Scope를 가진다는 것을 알수 있습니다. 

JavaScript 의 경우


function show()
{
   for (var i=0;i<5;i++)
   {
			var b = 10;
   }
console.log("B is ",b);
}
show();


// 결과
// B is  10



자바 스크립트의 Scope Chain 은 위와 같이 Function 을 가지게됩니다.


이에 대해서 JS 작성시 실수하였던 점이





   for(var i=0;i<10;i++)
  {   
        for(var j=0;j<10;j++)
        {
              for(var i=0;i<5;j++)
              {
               }

         }

        
  }
       









해당 식의 코드를 한번 짤일이 있었는데 디버그 하다가 애를 먹었던적이 있습니다.


처음 i 0 ~을 돌다가 3번째 for문에서 i가 4인 채로 끝나기 때문에  자기 밖으로나가면 i2가 된상태로 돌아야하지만


i4인채로 끝나서


첫번째 포문에서 i 0 1,2,3 부분이 건너 뛰고 바로 4로 넘어가는 현상이 생겼습니다.


js에서는 function Scope Chain 을 가지기 때문에 해당 부분에 유의 하여야 합니다.


최근 ES스펙이 오름에 따라서 let변수가 해당 C,C++의 block scope 를 가지게 도와주지만 해당 내용은 뒤에 작성하도록 하겠습니다.













아직까지 업무도중에 reduce를 쓸일이 없어서 reduce랑 reduceRight 가 몇번 건드리긴 했는데


제대로 해본적이 없다 보니 reduce에 대해 자세하게 알아보기로했다.


매번 return map forEach 만 사용했는데 


https://jsperf.com/native-map-reduce-vs-for/2


reduce가 엄청나게 파워풀하고 map filter forEach 를 전부 해결할수있는 만능 이라는것도  알게되면서


reduce에 대한 포스팅을 하려고합니다.

알아야 하는 JavaScript 


1. JavaScript Event Loop 에 대해 설명


2. JavaScript 에서의 비동기 처리 과정


3. Hoisting 이란


4. Closure 란


5. this 에 대해서 설명


6. Promise 에 대해 설명


알아야하는 front-end


1. 브라우저의 동작 원리 설명


2. Document Object Model (DOM)

Event bubbling and Capturing 설명

Event delegation


3. CORS 에 대한 설명


4. 크로스 브라우징 예시 


5. 웹 성능과 관련된 Issue


6. 서버사이드 렌더링 (SSR) 과 클라이언트 사이드렌더링 (CSR) 


7. CSS Methodology


8. normalize .css    vs reset.css


&& 이외 

1. 페이지 로드를 줄일 수 있는 방법을 나열 


1-1 이미지맵 

여러개의 이미지를 띄우지 않고 한개의 이미지에 사용되는 이미지들을 넣어 놓고 사용합니다.

login.png,logout.png,user.png을 따로 부르는것이 아닌 loginPage.png 라는 곳에 다 넣어 놓고

이미지를 픽셀로 짤라서 불러오는 방식을 사용합니다. 

2. CSS 애니메이션과 자바스크립트 애니메이션의 장단점을 설명하시오


3. 간단한 슬라이드쇼 페이지를 어떻게 개발할지 설명해보시오.





JavaScript 에서 생성자와 프로토타입은 겉으로는 비슷하게 동작하는 것으로 보이지만


실제로 내부적으로는 많은 다른 동작이 있습니다.


해당은 new를 통해서 생성자 함수로 만들어서 사용 하였습니다.


function SuperConstructor(arg){

    this.id = arg;
    
    this.getId = function(){
            return this.id;
    }
    this.setId = function(_id){
        this.id = _id;        
    }
}

var gdl = new SuperConstructor('q1w2e3r4');
console.warn(gdl.getId());    //q1w2e3r4

var gdl2 = new SuperConstructor('qwer1234');
console.warn(gdl2.getId()); // qwer1234




해당 코드를 Prototype으로 변경 해보겠습니다.





function SuperConstructor(arg){

    this.id = arg;
    
}
SuperConstructor.prototype.getId = function(){
			return this.id;
}
SuperConstructor.prototype.setId = function(_id){
			this.id = _id;
}
var gdl = new SuperConstructor('q1w2e3r4');
console.warn(gdl.getId()); // q1w2e3r4

var gdl2 = new SuperConstructor('qwer1234');
console.warn(gdl2.getId()); // qwer1234




두개의 코드 다 결과가 같습니다. 


하지만 내부적으로는 큰 차이가 하나 있습니다.


프로토타입의 경우에는 프로토타입 체이닝이라는 변수가 존재합니다. 


1번째 방식을 사용하게 되면 


메모리 사용되는 폼은 이와 같습니다.



( gdl - getId, setId, id) ( gdl2 - getId, setId, id) ( SupterConstructor - getId, setId, id)


2번째 방식을 사용하게 되면


메모리 사용되는 폼은 이와 같습니다.



(gdl - id)  ↘

                ->   (SuperConstructor -prototype.getId, prototype.setId)

(gdl2 - id) ↗  


와 같이 되며 gdl .setId일시 프로토타입 체이닝을 통해서 -> SupterConstructor 에 있는 값을 찾아가며


해당 함수에서 this.id로 지정이 되었기 때문에 this는 체이닝으로 부터 넘어온 gdl 이 된다.


그러므로 gdl 에 있는 id값을 지정하게 됩니다.


2번의 경우는 확실히 프로토타입 함수가 프로토타입 체이닝으로 인해서 중복 호출에 대한


최소화가 이루어졌기 때문에 


OOP 와 같은 프로그래밍을 하기 위해서는 Prototype 을 사용함을 권장합니다.




자바스크립트에서 this에 대해 공부하다 보면 이해한거 같다가도 클로저 함수가 들어오면 또 이해가 안되는 경우가 많아


this에 대한 이해를 IIFE 패턴에서 어떻게 사용되는지 확인해 보았습니다.


this는 함수 함수 scope 단위로 생성 됩니다. 라는 점을 알고 작성하겠습니다.


해당 객체를 통해서 this의 생성 범위를 확인 해 보면


iife = (function (){

var a = function(){

console.log('iife function a ', this);

                }

       return {

a:a,

       }

})();



결과 :


iife.a();

iife function a  {a: ƒ}


이제 함수 몇개를 추가하여서 iife라는 객체에서 return 되지 않는 함수에 대한 this 확인 

-> 이점이 처음에 this와 iife에 대해서 잘못 이해 하였던 부분이 있습니다.


c계열에서 class라고 생각하다 보면  iife라는 객체로 감싸져있기 때문에 어떤 함수여도 this는 iife라고 생각 했기 때문입니다.



iife = (function (){

		var outerFunction_aa = function(){

		console.log('iife function a ', this);
			
				// this.inner_d(); // error is not a function
				// this.inner_e(); // error is not a function

				inner_d();   // success    -> inner delcaration function  [ window ]
				inner_e();   // success    -> inner expression function  [ window ]
        }


  		// function declaration
		function inner_d(){
				console.log('inner declaration function', this);
        }
		// function expression
		var inner_e = function (){
				console.log('inner expression function',this);
        }

		var outerFunction_b = function(){
				console.log('outer expression function_b ' , this);
        }



       return {
		outer_a : outerFunction_a,
		outer_b : outerFunction_b,
       }

})();

결과 : 실행은 iife.outer_a(); 로 하였을때

this.inner_d();  

this.inner_e();  두 함수다 에러로 표시되며 메시지는 is not a function 

즉 this에 inner_d 가 없다는 뜻입니다. 

(js에서 inner_d가 프로퍼티인데 지정이 안되었을 경우는 undefined 로 되기 때문에 호출하여도 에러는 나지 않습니다.)

하지만 함수의 경우는 실행을 하여야 하기 때문에 정의되거나 함수이지 않은 경우는 is not a function 에러가 나타나게 됩니다.


하지만 this를 제외하고 실행시 

inner_d();  

inner_e();  두개의 함수다 실행되며 내부 함수에서 this는 [window] 가 잡힙니다.


??? IIFE 패턴으로 묶었는데 왜 window가 잡히는지 이해가 잘 안됩니다. 


-> 사실은 이게 class처럼 감싸진게 아닙니다. 


iife객체는 생명주기가 끝난  익명함수의 실행컨텍스트를 가지고 있습니다.


iife객체는 현재 return 되었던 outer_a 와 outer_b 만 을 가지고있습니다.


일반 함수에서 this는 [window]인것 처럼


IIFE패턴과 같이 위에 처럼 작성되어도 

return  { 

// closure space 

}


가 포함되어있지 않은 함수는 expression(함수 표현식) 이나 declaration(선언식) 이나 window를 지칭하게 됩니다. 


하지만 함수 자체(return 되지않은 inner_d)는 


iife.a() 형태로 직접 실행되지 않았기 때문에 this는 [window] 에 바인딩되게 된다.


this의 생성 조건은  해당 메서드를 호출한 객체로 바인딩 이기 때문이다.


그렇기 때문에


iife.outer_a(); 로 호출하였을 경우 outer_a()는 앞에 iife객체가 this가 되지만 해당 함수 내부에서 내부 함수를 호출하기 위해서는


inner_d();   // success    -> inner delcaration function  [ window ]
inner_e();   // success    -> inner expression function  [ window ]

해당형식으로만 선언할수 있기 때문이다.  해당 함수의 선언이 가능한 이유는 iife의 실행컨텍스트 안에 들어있기 때문에 그냥 선언해서


사용하여야 한다.  this로 안나오는 경우는 this가 window이기 때문이다.  


그러면 private하게 변수나 함수를 어떻게 사용하여야 할까


함수 선언식과 표현식은 호이스팅의 차이 유무가 있기 때문에 이후 코드는 표현식으로 사용하겠습니다.


정말 처음에 공부할때 바로 생각도없이 아 그러면 return 함수를 만들고 그안에서 this . value로 쓰면되겠다!


그러면 private로 쓸수 있을줄 알았다면



iife = (function (){
	var innerValue = 1;
		var outerFunction_a = function(){
			console.warn(this);
			console.warn('inner Value ', this.innerValue);	
		}

		var outerFunction_b = function(){
			console.warn('inner Value ', this.innerValue);				
        }

	// function expression
		var inner_e = function (){
			console.warn(innerValue);
        }



       return {
		outer_a : outerFunction_a,
		outer_b : outerFunction_b,
       }

})();

결과 : 실행은 iife.outer_a(); 로 하였을때

▶ : {outer_a:f, outer_b:f}

▶ : inner Value undefined 

undefined로 나온다. 왜 return 을 안했기 때문


innerValue :innerValue, 로 리턴을 해주면 동작은 하지만 그렇게 되면 private 라고 할수 있을까


iife.innerValue = 5 를 입력하게되면 내부값 역시 5로 바뀌기 때문이다. 


일단 내부 변수를 밖으로 빼내는거 자체가 좋은생각은 아니기 때문에 getter, 와 setter를 활용 한다.


또한 내부 함수를 스코핑을 통해서 실행시키기 위해서는


var this_ = this; 를 활용한다.


이에 대한 기본적인 구성은


iiife = (function (){
	var innerValue = 1;
	var arr= [0];
		var outerFunction_a = function(){
			console.warn(this);
			console.warn('inner Value ', innerValue);	
		}

		var thisChange = function(){
				console.warn('thisChange tihs');
				console.log(this);
				var _this = this;
				
				console.warn('forEach this');
					arr.forEach(function(item,index){
								console.log(this);
								console.log(_this);
                    });
				console.warn('map this');
					arr.map(function(item){
							console.log(this);
							console.log(_this);
                    });
			
				console.warn('arrow function this');
			
					arr.map( item => {
							console.log(this);
							console.log(_this);
                    });


					
        }

	// function expression
		var inner_e = function (){
			console.warn(innerValue);
        }

		var getValue = function(){
				this.innerValue;
        };
		
		var setValue = function(value){
				this.innerValue = value;
        };

       return {
		outer_a : outerFunction_a,
		thisUse : thisChange,
		setValue : setValue,
		getValue : getValue,
       }

})();
iife.thisUse();


arrow function 을 쓸 경우는 새로운  this가 바인딩되지 않습니다. 이것은 arrow function 에서 새롭게 포스팅 하도록 하겠습니다.


위의 코드 결과입니다.




getter,setter에 대한 포스팅은 


http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife 에 자세하게 잘 나와있어 링크 합니다.




재귀 함수 (Recursive Function)

재귀(Recursion) 에 따라서 내가 나를 호출하여 사용하는 함수라고 볼수 있다.


1개의 함수


void Recursive_fnc() 라는 함수에서 또 다시 자기 자신을 불러서 수행하는 방식을 말한다. 


그렇기 떄문에 재귀 함수 설계시에는 적절한 종료 조건을 만들어서 종료 할수 있도록 설계하고 구현 하여야 한다.


LISP 라는 언어는 재귀를 정말 밥먹듯이 쓴다고 한다. 여기서 따로 언급은 하지 않겠다.


필자는 이제까지 재귀 함수 는 왜 쓰는 걸까? 라고 하게 되면


C에서 속도가 빠르니까 ! 재귀가 속도가 빨라


하지만 Function Call 을 계속 해주기 때문에 아무리 Return 을 한다 해도 메모리상에 자꾸 참조되는 함수가 생기고 언제 


Seg Fault 가 날수 있기 때문에 매우 위험하다라는 생각을 가지고 있었다. 이건 단순한 자료조사가 아닌 카더라 통신과 


주관적인 생각이였을 뿐


갑자기 생각난 재귀함수에 대해서 어떠한 원리일까를 찾아 보던중 재미난 글을 발견 하였다. 


재귀의 가장 큰예는 팩토리얼 함수를 예로 들수가 있다. 1 ~ n 까지 곱하는 것


int factorial (int n)

{

if(n==0) return 1;

return (n*factorial(n-1));

}


정말 깔끔하며 가독성도 매우 높다. 하지만 이 재귀함수에는 문제점이 있습니다.


매번 함수마다 자기 자신을 호출한다는 점


1. 재귀적으로 함수를 지속적으로 호출시에 fac의 예를 들었을때 


return (n*factorial(n-1)); 이란느 부분이 있는데


만약에


100이라는 값이 들어오게 되면


factorial(100) * factorial(99) * factorial(98) ~.... 으로 1이 되어서 끝나기직전까지 호출만 이루어지는 상황이 발생하는데


함수 호출시 프로세스는 parameter, return values 등이 반환시에 되돌아갈 위치를 스택에 저장하게 되는데


지속적으로 많은 호출이 나타나게되면 스택에 부모함수부터 데이터들을 쌓아 놓게 되는데 스택같은 경우는 무한정으로 


존재하지 않기 때문애 넘치는 Stack OverFlow가 발생할수 있습니다.


팩토리얼같은 경우는 어차피 컴퓨터가 처리하는 수의 범위를 넘어 버리기 때문에 불가능합니다.


2. 또한 스택에 데이터를 자꾸 존재한다는 것은 메모리의 사용량이 증가 된다는 뜻이 되며 


스택에 데이터를 쌓을때 이 값을 복사하게 되는데 이 쯤에서 다시 문제가 생기게 된다. 


피보나치 수열을 예로 들어 보게 되면


F(n+2) = F(n+1) + F(n) 

unsigned int fibonacci(int n)

{

if(n==0) return 0;

else if(n==1) return 1;

else return (fibonacci(n-1)+ fibonacci(n-2));

}



// 재귀 함수의 호출 시간 스크랩 - http://www.nicklib.com/application/2953


보시는거와 같이 2개의 자식 함수를 재귀적으로 부르고 있으며 해당 함수에 대한 시간 입니다.


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

 N        결과값            걸린시간

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

10           55                      2마이크로초

20         6765                    225마이크로초

30       832040             34밀리 391마이크로초

40    102334155        3초 544밀리 659마이크로초

50  12586269025   7분 15초  68밀리 740마이크로초

60 1548008755920 14시간 40분 28초 531밀리 693마이크로초



N이 30일경우에는 1초도 걸리지 않기 때문에 괜찮지만 40부터는 눈에 띄게 계산에 대한 시간이 보여지는 것을 알 수 있습니다.


해당 참조하였던 블로거는 n이 50인 값부터 int64으로 변환하여서 돌렸다고 합니다.


60에서 14시간이 걸린것을 보면 오래걸린건지 아닌지 분간이 잘 되지않지만 이 계산법에 대한 코드를


비재귀 함수로 구현하였을때의 속도를 비교하게 되면 재귀의 문제점을 파악할 수 있습니다.



비재귀 함수인


unsigned int fibonacci2(int n)

{

unsigned int a =1, b=1, c=1;

int (n==0) return 0;

for(;n;2;n--)

{

c=a+b;

a=b;

b=c;

}

return c;

}


재귀에 비하여 확실히 복잡하긴 합니다.  해당 소스에 대한 재귀 결과입니다.

<br />

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

 N               결과값            걸린시간

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

10                    55             0초

20                  6765             0초

30                832040             0초

40             102334155             0초

50           12586269025             0초

60         1548008755920             0초

70       190392490709135             0초

80     23416728348467685             0초

90   2880067194370816120             0초

100  3736710778780434371             0초

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

재귀함수에 대한 문제점을 파악할수 가 있는 결과입니다. 해당 테스트 블로거의 PC의 CPU 사양은 듀얼코어 1.8인 것을 감안하면(고사양은 아님)

엄청난 차이라고 할수 있습니다.


언제나 재귀함수에 대해 검색하면 스택 오버플로우 메모리문제, 속도 문제 등이 나타나는데 절대 안좋은점만이 있는 것은 아닙니다. 


안좋기만한 함수가 왜구현되고 왜 사용되고 재귀함수라는 말이 생겨나고 꼭 프로그래밍 책에 나오는 이유가 있습니다.


보시면 알겠지만 가독성이 매우 뛰어나게 됩니다. 재귀에 대한 다른 이야기는 다음에 찾아서 써보도록 하겠습니다.





'개발일지(Language) > Python(3.x)' 카테고리의 다른 글

8 - 쉬어가기(연습문제)  (0) 2016.07.26
7 - 문자열 포매팅(발전)  (0) 2016.07.26
6 - 문자열 포매팅(기본)  (0) 2016.07.26
5 - 문자열 과 자료형  (0) 2016.07.25
4 - 연산자  (0) 2016.07.25
# 세미나 자료를 위한 프로그램 제작
# 0,0 1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9
# 0 1 2 3 4 5 6 7 8 9


# 입력된 문자열 에 a-z 가 포함이 되지 않음을 체크한다. 포함이 되었을 경우 -1 을 반환하며 잘못된 문자열임을 알려준다.
# 0~ 9 가 정상적으로 포함되어있을시에는 해당 문자열열 그대로 반환 한다.
# 알파벳 유효성 검사
def rrn_parsing(rrn):
alpha_sum = 0
parsing = "qwertyuiopasdfghjklzxcvbnm"
alphabet_list = []
i = 0
j = 0
z = 0
# 알파벳 리스트 추가
while i < 26:
alphabet_list.append(parsing[i].lower())
i = i + 1
# 알파벳 소문자 서칭
alphabet_list.sort()

# print("alphabet_list {0}".format(alphabet_list))
# parsing before
print("Input RRN ", rrn)
while j < 26:
alpha_sum = alpha_sum + rrn.count(alphabet_list[j])
# print("InPut RRN {0} counting alpha {1}".format(rrn, alphabet_list[j]))
j = j + 1
# print("print alpha_sum {0}".format(alpha_sum))

# 알파벳 대문자 서칭 ( 알파벳 리스트 전부 제거 )
i = 0
j = 0
while i < 26:
alphabet_list.pop()
i = i + 1

i = 0
# 대문자 셋팅
while i < 26:
alphabet_list.append(parsing[i].upper())
i = i + 1
# 대문자 서칭
while j < 26:
alpha_sum = alpha_sum + rrn.count(alphabet_list[j])
j = j + 1

if alpha_sum > 0:
return 0
if alpha_sum == 0:
return 1


# 주민 등록번호 유효성 검사
def rrn_len(rrn):
true_or_false = 0
check_num=['0','1','2','3','4','5','6','7','8','9']
check_sum = 0
# parsing before
# print("parsing before ", rrn)
rrn_parsing = rrn.replace(" ", "")
# print("parsing after ",rrn_parsing)
# parsing after
i=0
while i<10:
# 0 = 0 + 0 갯수
check_sum = check_sum + rrn.count(check_num[i])
i = i + 1
if check_sum == 13:
print("RRN is Success ", check_sum)
true_or_false = 1
if check_sum < 13:
print("RRN is Failed ", check_sum)
true_or_false = 0
return true_or_false


# 유효성 검사 반환값에 대한 Split 함수
def rrn_regular_expression_parsing_msg(rrn):
return rrn


# 유효성 검사
def rrn_regular_expression(rrn):
# char_checksum
if rrn_parsing(rrn) == 0:
return "문자열이 포함되어있습니다."
if rrn_len(rrn) == 0 :
return "숫자가 13장이 넘습니다."
return rrn


# 12개
RRN_true = "11111111111111"
RRN_false = "90 1 0 2 7 1 1 5 6 0 2 5"
RRN_char = "abcde"
RRN_Upper = "ABCDEF"
RRN_Count = 13
i = 0
# 0~ 12 까지 11번까지가 11
# print(RRN_false[12]) 5가 반환 됩니다.

print("*"*60)
print("*"*24 + "Python Start" + "*"*24 )
print("*"*60)


# a-z 문자열 삽입
print(rrn_regular_expression(RRN_Upper))
# 성공
#print(rrn_regular_expression(RRN_false))
# 14자
#print(rrn_regular_expression(RRN_true))



'개발일지(Language) > Python(3.x)' 카테고리의 다른 글

9 - 쉬어가기(재귀함수)  (0) 2016.07.27
7 - 문자열 포매팅(발전)  (0) 2016.07.26
6 - 문자열 포매팅(기본)  (0) 2016.07.26
5 - 문자열 과 자료형  (0) 2016.07.25
4 - 연산자  (0) 2016.07.25

일반적인 문자열 포매팅에 대해서 확인 해보았는데


"Hello World %d" % 5


Hello World 5 


가되는데 이런 방식이 아닌


"Hello World {0}".format(5)

Hello World 5 가 된다.


"Hello World %s" %"Five"

"Hello World {0}".format("Five") 


num =5

format ="Five"

"Hello World {0} is {1}".format(num,format)


'개발일지(Language) > Python(3.x)' 카테고리의 다른 글

9 - 쉬어가기(재귀함수)  (0) 2016.07.27
8 - 쉬어가기(연습문제)  (0) 2016.07.26
6 - 문자열 포매팅(기본)  (0) 2016.07.26
5 - 문자열 과 자료형  (0) 2016.07.25
4 - 연산자  (0) 2016.07.25

a = "Hello World"


라고 되어있을때 Hello World의 값을  바꿀수가 없다. 5장에서 말했듯이 immutable 형이라고 도 한다고 한다.


a[0] = 은 지금 H값이 되겠지만

a[0] = "A"로 바꿀수는 없는 것이다.


하지만 조금 주먹 구구식으로 말하자면


a="String Format"

print(a[:1])
# S t r i n g
# 0 1 2
# 0 <= a < 1
# S 가 출력

# S t r i n g
# 0 1 2
# 2 < = a <
# r 부터 출력되게 된다.
print(a[2:])
b = a[:1] + 'T' + a[2:]
print("formatting a -> ",b)
# 새로운 문자를 출력하기 위해서 일단 주먹 구구식으로 변환이 가능 하다


결과

S

ring Format

formatting a ->  STring Format


현재 보여진것은 문자열 포매팅은 아니고 기본적인 변화와 문자열이 선언후에는 변하지 않는 점을 알수 있도록 하였다.


format="Hello %d World " % 3
print(format)


결과


Hello 3 World 


format="Hello %s" % "World"
print(format)

결과

Hello World


숫자와 문자열도 포매팅이 되는 법을 알수가 있다. !!    %d %s 는 C언어에서도 자주 보아왔던 포매팅 방식이다.

var을 이용한 포매팅


위에 예제에서 숫자만 변수로 따로 선언 해주면 된다.

number =3
format = "Hello %d World " % number

print(format)


결과

Hello 3 World 


두개이상의 포매팅을 해주는 경우 방법

format = "World"
number = 3

second_format = "Hello %s is %d" % (format,number)

print(second_format)

결과

Hello World is 3


, 로 구분하여서 넣으면 된다.  printf("",a,b)와 비슷한 맥락 


파이썬 문자열 포맷 


1.       %s        문자열(string)

2.       %c        문자 1개(character)

3.       %d        정수(Integer)

4.       %f        부동 소수(floating-point)

5.       %o        8진수

6.       %x        16진수

7.       %%       '%' 문자 자체

&& "%50s" -> 전체 50자의 문자열 공간에서 우측으로 정렬 하고 나머지는 공백으로 놓게된다.


C언어에서 50자를 띄워쓰기를 하는 경우와 다른 점을 인지한다.

"%-50s" -> 전체 50자의 문자열 공간을 잡고 좌측으로 정렬후 나머지 우측은 공백으로 놓게 된다.



%0.3f = 소수점 세 번째 자리 까지 나타낸다.

앞에 0 대신에 숫자가 들어오게 되면 양수일 경우에는 위와같이 문자열 공간의 개수를 잡고 공백을 넣는다.

%10.3f 

문자열 공간을 10칸을 잡고 우측 정렬을 하게된다. ex: "%10.3f" % 3.1452452

 ㅁ ㅁ ㅁ ㅁ ㅁ ㅁ ㅁ ㅁ ㅁ ㅁ 

                     3  .   1  4  5 

로 잡히게 된다. 


문자열 관련 내부 함수 

temp="Hello World"
print("Hello World 'l' count",temp.count('l'))
print("Hello World 'd' find ",temp.find('d'))

find 

count

index


결과

Hello World  'l' count 3

Hello World  'd' find  10


find의 경우 찾는 문자열이 없다면 -1을 반환하게 된다. d의 문자열이 처음 나오는 위치인 10을 반환하게 된다.

index의 경우도 find와 같은 기능을 한다. 하지만 찾는 문자열이 없는 경우에 대해서는 오류를 발생 시킨다.



uppder 함수 


temp ="hello world"

print(temp.upper())


결과 


HELLO WORLD


lower 함수

temp = "HELLO WORLD"

temp.lower()


결과


hello world


join 함수 (해당 함수와 같이 split 함수에 대해서는 따로 작성) 해당함수에 대해서 는 이해를 돕다 보니


작성할 내용이 많아져서 해당에 대해 따로 작성 하도록 함 


lstrip(왼쪽 공백 지우기)

rstrip(오른쪽 공백 지우기)

strip(양쪽 공백 지우기)

replace(바뀌게 될 문자열, 바꿀 문자열) 문자열을 바꿈

오해하지 말아야 할 부분은

temp ="Hello World Start to Start"
print(temp.replace("Start","End"))
print(temp);

결과는

Hello World End to End

Hello World Start to Start

가 나오게 된다. 변환을 하기는 하지만 파이썬에서는 immutable 에 대해서 절대로 까먹지 말아야 한다.

temp를 Hello World Start to Start로 선언을 했을시에 절대로 이 값에 대해서는 변화가 이루어지지 않는다.














'개발일지(Language) > Python(3.x)' 카테고리의 다른 글

8 - 쉬어가기(연습문제)  (0) 2016.07.26
7 - 문자열 포매팅(발전)  (0) 2016.07.26
5 - 문자열 과 자료형  (0) 2016.07.25
4 - 연산자  (0) 2016.07.25
3 - 숫자형  (0) 2016.07.25

+ Recent posts