파이썬(Python)




"인생은 너무짧다. 그래서 파이썬이 필요하다."

파이썬은 짧은 코드에서 나오는 효율성 뿐만아니라 들여쓰기로 만들어지는 자동 정렬,

어떤 분야든 가리지 않고 닥치는대로 사용할 수있는 범용성 등 많은 무기를 가지고 있다.

이 때문인지는 몰라도 2017년 6월 기준 프로그래밍 점유율 수준은 당당하게 4위를 차지하고 있다.





(파이썬의 창시자 - 귀도 반 로썸)


파이썬이 최근에 주목받고 있다고 생각할지 모르겠지만 발표시기는 1991년,

웹 서비스가 일반인들에게 널리 상용화되기 전에 나온 언어이다.

언어를 만든이는 귀도 반 로썸(Guido van Rossom)으로 

1989년 크리스마스 주에 연구실이 닫혀있어 심심한 김에 만들었다고 한다.

리누스나 귀도 둘다 심심한 김에 걸작을 만들었다는데 있어서, 위대한 공돌이의 피가 흐르는 것 같다.

파이썬이라는 이름은 귀도가 즐겨보던 6인조 코미디 그룹 몬티 파이썬에서 따왔다.


문법이 매우 쉬워서 C를 제치고 초보자에게 입문용으로 추천되는 언어이며,

벌써 몇몇 대학교에서는 인문학과 교양 수업으로 편성되는 저력을 보이고 있다.

그러나 사용하는 사람이 많은 만큼 까는 사람도 많다. 

어떤 커뮤니티에서는 C 와 파이썬 중 어떤 언어로 입문하는게 좋은지 끝없는 토론이 이루어지고 있다.






파이썬의 특징은 2버전과 3버전으로 나뉜다는 것이다.

2버전의 불편함이 끊임없이 대두되었고, 

결론적으로 하위 호환성을 포기하고 3버전을 출시했는데 기본적으로 둘사이에 호환성은 낮다.

그러나 파이썬 2를 3으로 바꿔주는 컨버터 등이 제공되어 완전히 갈아 엎을 필요는 없어보인다.


당연한 말이지만 파이썬 2가 먼저 나왔기 때문에 3가 출시 되었을 때는 당연히 2로 구현된 모듈이나 라이브러리가 많았다.

그러나 3를 주력으로 지원하고, 시간이 지나며 모듈과 라이브러리 데이터도 늘어나면서 현재는 3를 목표로 공부하는것이 좋다.

이유는 위에서 언급한 내용과, 파이썬 2에 대한 지원 2020년을 기점으로 종료되기 때문이다.







이러한 파이썬의 장점은 여러가지가 있는데 가장 첫 번째가 생산성이 높다.

위의 그림은 파이썬에 입문했던 사람이라면 한번쯤 보았을 만화인데, 인터프리터 언어이며,

High level의 자료형과 좋은 모듈을 제공해주는 덕분에 단 몇줄의 코드만드로 많은걸 해낼수 있다.


또한 들여쓰기로 블록을 구별하기 때문에 프로그래밍을 하는 것만으로 코드의 모양이 저절로 정리된다.

파이썬이 가지는 특징이자 장점이라고 할수 있다.


마지막으로, 거의 모든 분야에 대해 지원을 하기 때문에, 프로젝트를 구현할 때 어떤 언어로 할지 모르면 파이썬을 선택하면 된다.

그 만큼 파이썬이 미치는 영향이크며, 오히려 파이썬으로 할 수 없는 것을 찾기가 더욱 어렵다.

파이썬은 발전하여 Django나 Flask 프레임워크로 웹 분야까지 섭렵하게 되었다.

이 프레임 워크를 사용할경우 짧은 시간내에 많은 것을 구현할수 있다는 장점이 있지만

프레임워크가 제공하는 범위에 한정적이라는 단점이 있다.

 


저작자 표시
신고

믹스인(Mixin)



앞서 파이썬에서 다중 상속에 대해 살펴보았다.

다중 상속에서 루비에 대해 다루지 않은 이유는 루비는 다중상속을 지원하지 않기때문이다.

대신 믹스인이라는 세련된 방법을 사용한다. 믹스인이라는 것은 객체와 모듈의 관계이다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# ruby
module M1
  def m1_m
    p "m1_m"
  end
end
module M2
  def m2_m
    p "m2_m"
  end
end
class C
  include M1, M2
end
= C.new()
c.m1_m()
c.m2_m()
cs


위의 코드를 찬찬히 읽어보면 단번에 어떤 부분이 믹스인인지 알수 있을 것이다. 바로 include라는 부분이다.

먼저 모듈 M1과 M2가 선언되며, 클래스 C가 이 모듈들을 include한다.

모든 과정이 끝난후에 C 클래스의 인스턴스를 만들어 주고, include한 두 모듈들의 메소드를 호출하면

에러없이 정상적으로 동작하게 된다.

따라서, C가 M1과 M2의 메소드를 포함하고 있는 것처럼 행동하는 것이 믹스인의 핵심 이다.



출처 : 생활코딩, 파이썬&루비


저작자 표시
신고

다중상속(Multiplex Inheritance)




기존에 부모 객체로 부터 메소드를 받을 수 있는 것을 상속이라고 하며,

여러개의 부모객체로 부터 상속을 받는 것을 다중 상속이라고 한다.

객체 지향을 하는 언어들이 모두 다중 상속을 지원 하는 것은 아니며, 대부분은 지원하지 않는다.

이유는 죽음의 다이아몬드라는 다중상속의 크나큰 단점때문인데,

이 때문인지 몰라도 루비에서는 다중상속을 지원하지 않고 파이썬에서는 지원한다.

대신 루비에서는 Mixin이라는 기능을 이용해서 비슷한 목적을 이룰수 있다.

따라서 이번에는 파이썬 코드만 보도록 하겠다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# python
class C1():
    def c1_m(self):
        print("c1_m")
    def m(self):
        print("C1 m")
 
class C2():
    def c2_m(self):
        print("c2_m")
    def m(self):
        print("C2 m")
 
class C3(C2, C1):
    def m(self):
        print("C3 m")
 
= C3()
c.c1_m()
c.c2_m()
c.m()
print(C3.__mro__)
cs


C3는 C1과 C2로부터 상속을 받는다.

따라서 C3의 뒤쪽에 C1과 C2를 명시해줌으로써 상속을 받게 된다.

이로인해 기존에 부모객체가 가지고 있던 모든 메소드를 사용할 수있게되며,

C1이 가지고 있는 m이라는 메소드만 오버라이드 한 상태이다.

따라서 아래의 메소드 호출 코드 3줄은 모두 정상적으로 동작하게 된다.


이렇게 다중상속은 상당히 편리한 기능을 제공하고 있는듯 하지만 제한적인 환경에서만 유용하다.

실제로 규모가 커진 상태에서 다중 상속을 사용하게되며면, 알수 없는 여러가지 문제점이 발생하기때문에

다중상속을 사용하는 부분에서는 상당히 신중해야한다.

이때문에 일부 언어들이 다중상속을 지원하지 않는 것이다.


그렇다면 다중상속이 일으킬수 있는 복잡한 상황들이란 어떤것일까.

만약 부모 객체에서 같은 이름의 메소드를 동시에 가지고 있다면 어떤것을 호출해야하는지 생각해보자.

자신이 만든 부모 객체가 아니면 내부 구조가 어떻게 이루어 져있는지 모르기때문에 상황이 더욱 복잡해진다.

또한 상속받는 부모객체도 부모가 있다면 상황은 걷잡을수 없이 악화된다.

소프트웨어는 조금의 조작 만으로도 금방 복잡해지기 때문에 이와같은 상황은 자주 일어날수 있다.


부모 객체에서 같은 이름의 메소드를 호출하면, 앞쪽에 등장한 부모객체의 우선 순위가 높다.

만약 객체.__mro__라는 명령어를 호출하면 우선순위를 확인할 수 있다.




출처 : 생활코딩, 파이썬&루비



저작자 표시
신고

객체와 모듈




1
2
3
4
5
6
7
8
9
# test.py
import lib
obj = lib.A()
print(obj.a())
 
#lib.py
class A:
    def a(self):
        return 'a'
cs


이번에는 객체를 모듈화 하는 것에 대해 알아보도록 한다.

먼저 클래스에 대한 모듈 파일을 만든다.

이렇게 만들어진 모듈 파일을 사용할 파일에서 import 시켜야한다.

그리고 나서 모듈 내부의 객체 이름으로 인스턴스를 만들어 준다.

결과적으로, 해당 객체 인스턴스가 생성되고, 내부 메소드를 사용할 수 있게된다.





1
2
3
4
5
6
7
8
9
10
11
12
13
# test.rb
require_relative 'lib'
obj = Lib::A.new()
p obj.a()
 
#lib.rb
module Lib
  class A
    def a()
      return 'a'
    end
  end
end
cs


다음으로는 루비 코드이다.

루비도 마찬가지로 module 키워드를 통해 모듈을 생성해준다.

그리고 모듈을 사용할 파일의 위치에서 require 키워드를 통해 로드해 준다.

여기서 A라는 클래스를 가져오기 위해서는 ::(더블 콜론)을 사용해준다.

그리고 인스턴스를 만들어야 하므로 객체 뒤에 new 키워드로 인스턴스를 생성해준다.

루비 코드도 마찬가지로 모듈로 부터 객체를 불러온후 인스턴스가 생성되어 내부의 메소드를 사용할 수 있게된다.


이렇게 모듈로 객체를 분리하게 된다면, 파일 마다의 코드 길이가 짧아지고 가독성이 높아지며,

하나의 모듈을 여러개의 다른 파일에서 사용할 수 있으므로 재사용성이 높아진다.



출처 : 생활코딩, 파이썬&루비


저작자 표시
신고

오버라이드(Override)




오버라이드는 재정의라는 의미를 내포하고 있다.

상속이라는 개념에서 상당히 중요한 기능이며, 복잡해진 객체 지향을 좀 더 잘 사용하기 위해 만들진것이다.


오버라이드는 상속 받은 메소드를 재정의 하는 것을 말한다.

부모 객체에서 자식 객체로 메소드가 넘어갈 때 이 메소드의 기능을 수정 하기 위해

해당 메소드의 코드를 다시 작성하는데 이것이 오버라이드이다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# python
class C1:
    def m(self):
        return 'parent'
class C2(C1):
    def m(self):
        return super().m() + ' child'
    pass
= C2()
print(o.m())
 
# ruby
class C1
  def m()
    return 'parent'
  end
end
class C2 < C1
  def m()
    return super()+' child'
  end
end
= C2.new()
p o.m()
cs


위의 코드는 오버라이드에 대한 예제이다.

먼저 파이썬을 보면, C2는 C1의 자식 객체이다. 즉, C1으로 부터 상속받은 객체이다.

C2 내부에 pass는 비어있는 객체이므로 에러를 내지않고 계속 실행시키라는 의미이다.

C2 에서는 부모객체로 부터 받은 m 메소드를 오버라이드한다.

m 메소드 내부의 super는 부모객체를 가리키며, 따라서 super().m()은 부모객체의 m 메소드를 호출하는 것이다.

결과적으로 실행시 parent child라는 문자열이 호출된다.


다음으로 루비 코드를 살펴 보자.

문법적으로 차이가 있지만 오버라이드의 사용방법은 파이썬과 차이가 나지 않는다.

결과적으로 오버라이드 후에도 파이썬 코드와 결과 값이 같다.

다만 차이가 나는것은 super 메소드인데, 루비에서는 super는 부모 객체를 가리키지 않고

super가 소속되어있는 메소드와 같은 부모객체의 메소드를 가리킨다.



출처 : 생활코딩, 파이썬&루비


저작자 표시
신고

클래스 멤버(Class Member)




1
2
3
4
5
6
7
# ruby
require 'date'
d1 = Date.new(200011)
d2 = Date.new(201011)
p d1.year()
p d2.year()
p Date.today()
cs


지금까지 배운 변수와 메소드는 '인스턴스 멤버'였다.

이번에 배울 내용은 '클래스'에 소속 되어있는 변수와 메소드이다.

그렇다면 인스턴스의 멤버와 클래스멤버의 차이점과,

왜 이런 차이점을 가지고 있는지에 대해 생각해보자.


먼저 루비에서 날짜에 대한 기능을 가지고 있는 객체를 살펴보자

require 로 date객체를 불러온 후 d1이라는 변수에 Date 객체를 이용해서 인스턴스를 만든다.

똑같은 방법으로 d2 변수에도 인스턴스를 만든다.


현재 d1에는 2000년 1월 1일 이라는 데이터를 가지고 있으며, d2에는 2010년 1월 1일 이라는 데이터가 있다.

이 상태에서 d1 인스턴스에 속해 있는 year라고 하는 메소드를 실행시키면 

이 메소드는 자신이 속해있는 d1이라는 인스턴스의 내부에 저장되어있는 년도의 값을 리턴한다.

이처럼 year라는 메소드는 d1에 속해있기때문에 내부에 소속되어있는 2000이라는 값을 리턴하는 것이다.

반대로 밑에 있는 year는 d2에 소속이므로 d2의 내부값인 2010을 화면에 출력하게된다.


여기서 중요한점은 year라는 메소드들은, 하는일은 같지만 각각의 메소드들이 누구의 소속이느냐에 따라서

그 소속된 인스턴스의 내부값을 사용해서 결과를 리턴한다는 것이다.

바로 그런점에 각각의 메소드는 각각의 인스턴스의 소속되어있다 라고 할수 있다.


이번에는 Date라는 클래스를 직접 지정하고 today라고 하는 메소드를 호출해서 출력해보자.

결과는 현재, 오늘의 값이 나오게 된다.

위에 있는 2개의 메소드와 밑에 있는 메소드의 가장 큰 차이는 두 메소드는 각각 인스턴스의 소속이었으나,

아래의 메소드는 클래스 소속이라는 것이다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
# ruby
class Cs
  def Cs.class_method()
    p "Class method"
  end
  def instance_method()
    p "Instance method"
  end
end
= Cs.new()
Cs.class_method()
i.instance_method()
#Cs.instance_method() 오류발생
#i.class_method() 오류발생
cs


이번에는 우리가 직접 클래스에 소속되어있는 멤버를 활용해서 코드를 작성하는 방법을 알아보자

먼저 루비 코드이다.

Cs라는 클래스를 선언하고 안에 메소드를 만들어준다.

위의 코드에서 클래스안에 2개의 메소드가 있는데 두 메소드의 차이점을 찾아보자.

첫번째 메소드는 메소드 이름 앞에 소속되어있는 클래스 이름이 붙어 있다.

이렇게 메소드 이름앞에 클래스 이름이 붙어 있으면 클래스 멤버가 된다.


따라서 아래에 해당 메소드를 호출할때, Cs.class_mathod와 같이 클래스 이름으로 호출해야하며

인스턴스 멤버는 해당 인스턴스로부터 호출해야한다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
# python
class Cs:
    @staticmethod
    def static_method():
        print("Static method")
    @classmethod
    def class_method(cls):
        print("Class method")
    def instance_method(self):
        print("Instance method")
= Cs()
Cs.static_method()
Cs.class_method()
i.instance_method()
cs


다음은 파이썬의 클래스 멤버 생성 예제이다.

파이썬은 루비와 다르게 클래스 멤버로 해당하는 메소드가 2가지 종류가있다.

 static 메소드와 class 메소드가 그것이다.


우선 인스턴스 메소드에는 첫번째 인자로 self가 들어가게 된다.

그리고 static 메소드와 class메소드를 설정하기 위해서 해당 메소드 위에 @ 장식자를 붙여준다.

이렇게 @staticmethod, @classmethod로 구분하게 된다.

또한 classmethod는 첫번째 인자로 cls를 가져야한다. 이 cls는 클래스를 가리킨다.


이와 같은 형식으로 static과 class를 선언할 수 있다.

지금 단계에서는 static과 class를 동일 하다고 생각하자.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ruby
class Cs
  @@count = 0
  def initialize()
    @@count = @@count + 1
  end
  def Cs.getCount()
    return @@count
  end
end
i1 = Cs.new()
i2 = Cs.new()
i3 = Cs.new()
i4 = Cs.new()
p Cs.getCount()
cs


다음은 클래스 멤버 중에서 클래스 변수이다. 먼저 루비 코드이다.

위의 코드에서 바로 알수 있듯이 @@가 2개 붙어있으면 클래스 변수가 된다.

클래스 변수는 모든 인스턴스가 공유하는 변수이다.

따라서 인스턴스를 만들때마다 클래스 변수가 1씩 증가했으므로 최종적으로 3이 출력된다.


다시 말하자면 @가 1개 붙어있을때는 인스턴스변수이며, 인스턴스마다 생성되므로 모두 다른 값을 가질수 있으나

@@가 2개 붙어있는 것은 클래스에 소속된 클래스 변수이므로 모든 인스턴스에서 값을 공유하게 된다.





1
2
3
4
5
6
7
8
9
10
11
12
13
# python
class Cs:
    count = 0
    def __init__(self):
        Cs.count = Cs.count + 1
    @classmethod
    def getCount(cls):
        return Cs.count
i1 = Cs()
i2 = Cs()
i3 = Cs()
i4 = Cs()
print(Cs.getCount())
cs


이번에는 클래스 변수의 파이썬 버전이다.

클래스 변수를 만들기 위해서 Cs를 변수 앞에 붙여준다. 

이 때 주의할 점은 class 안, 메소드들의 밖에 있는 변수는 자동으로 클래스 변수로 선언되기때문에 

그 변수 앞에는 클래스 이름을 붙이면 안된다.

따라서 메소드 내부에서 클래스 변수에 접근할 때만 클래스 이름을 붙여준다.



출처 : 생활코딩, 파이썬&루비



저작자 표시
신고
  1. ruby_newbie 2017.06.29 15:26 신고

    본문의 Class Cs, ruby 변수에서 initialize가 4번 되었으니 4를 print하는 것이 맞지 않나요?

상속(Inheritance)



우선 비유를 통해 상속을 알아보자.

우리가 자전거를 만든다고 했을때, 부품들을 조합해서 만들게된다.

이렇게 사용되는 부품을 함수라고 생각해보자.


이렇게 함수라는 부품을 조합해서 자전거라는 객체를 만들었다.

그리고 이 자전거를 다른사람에게 팔았는데, 팔린 후 새로운 기능을 달고싶어했다.

결국, 자전거에 전조등을 달게 되었는데 기존에 깔끔하게 자전거 기능만 담고있던 자전거에

전조등의 기능을 추가하면서 새로운 객체가 되었다.


위의 예 처럼 새로운 기능을 추가해서 새로운 객체를 만드는 것.

이것을 상속(Inheritance)이라고한다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#python
class Class1(object):
    def method1(self): return 'm1'
c1 = Class1()
print(c1, c1.method1())
 
class Class3(Class1):
    def method2(self): return 'm2'
c3 = Class3()
print(c3, c3.method1())
print(c3, c3.method2())
 
class Class2(object):
    def method1(self): return 'm1'
    def method2(self): return 'm2'
c2 = Class2()
print(c2, c2.method1())
print(c2, c2.method2())
cs


먼저 파이썬의 상속에 대해 알아보자.

첫번째로 일반적인 클래스인 Class1을 만든다.

이 클래스 내부에는 m1이라는 문자를 리턴하는 method1만 선언되어있다.

여기까지는 우리가 이때까지 배운 객체 생성이다.


다음으로 Class2는, 상속이라는 개념이 없을 경우 우리가 사용하는 방법이다.

Class2는 method1이 이미 Class1에 선언되어있더라도, 받아서 사용할수가 없기때문에 다시한번 선언해야한다.

결과적으로, 상속을 사용하지 않을 경우 프로그램의 코드가 길어지며 재활용성이 떨어지게 된다.

이로 인해 할수 있는것은 상속도 프로그래밍의 재활용성과 효율성을 추구하는 결과물이라는 것이다.


마지막으로 Class3는 Class1으로부터 상속받는 객체이다.

상속을 하기위해서는 우리가 객체를 만들기 위해서 적어주던 객체이름(Object) 양식에서

Object 자리에 상속 받을 객체 이름을 넣어주면 된다.

우리는 Class1을 상속받으므로 Class1의 이름을 넣어주자.

자바로 치자면 이 괄호안에 상속 받을 이름을 넣는것이 extends와 비슷하다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# ruby
class Class1
    def method1()
        return 'm1'
    end
end
c1 = Class1.new()
p c1, c1.method1()
 
class Class3 < Class1
    def method2()
        return 'm2'
    end
end
 
c3 = Class3.new()
p c3, c3.method1()
p c3, c3.method2()
cs


다음은 루비이다.

파이썬으로 상속이 없을 경우를 살펴보았으니 바로 상속으로 넘어가도록 하겠다.

우선 위의 코드는 파이썬과 기능적으로는 동일하다.

루비에서 상속을 하기 위해서는 클래스 이름 뒤에 < 기호와 상속 받을 클래스의 이름을 입력하면된다.


파이썬과는 조금 다르지만 똑같이 동작하는데, 이는 객체지향을 기반으로 한 언어들이

문법적으로만 차이를 보이며, 개념적으로는 거의 동일하기 때문이다.




출처 : 생활코딩, 파이썬&루비




저작자 표시
신고

캡슐화(Encapsulation)



객체는 규모 있는 애플리케이션을 만드는 과정에서 필요한 기능이다.

따라서 일반적인 프로그래밍 과정에서 객체의 필요성에 대해 못 느낄 수도 있다.

객체는 부품과 같다. 이러한 객체를 조립해서 큰 프로젝트를 만들어 가는 것이다.

따라서 좋은 객체를 만드는 것은 좋은 부품을 만드는 것이며, 이를 위해서 여러가지 조건을 충족해야한다.

그 중에 하나가 인캡슐레이션, 즉 캡슐화이다.


캡슐화란 객체가 어떤 일을 하는지와 상관없이 견고한 케이스로 감싸듯 외부의 영향을 받지 않게 하는 것이다.

즉, 이러한 케이스, 캡슐을 씌우는 것은 외부로부터 영향을 받아 변경되지 않도록 하는 것이다.

함수나 변수도 캡슐로 감싼 예 중의 하나이다.

함수의 조건문 반복문 등도 함수라는 캡슐로 싼 것이나 다름없고, 이러한 함수를 다시 묶어서 모듈로 감싼것이다.

객체도 이와 같은 맥락에서 내부의 동작을 보호하기 위한 캡슐이라고 할 수있다.





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
# python
class C(object):
    def __init__(self, v):
        self.value = v
    def show(self):
        print(self.value)
 
c1 = C(10)
print(c1.value)
c1.value = 20
print(c1.value)
c1.show()
 
# ruby
class C
  def initialize(v)
    @value = v
  end
  def show()
    p @value
  end
end
c1 = C.new(10)
# p c1.value
# c1.value = 20
c1.show()
cs

객체에 이를 적용시키면 인스턴수 변수의 수정에 대해 캡슐화를 적용할 수 있다.

파이썬에서 인스턴스 변수는 인스턴스 외부에서 접근하여 수정 및 사용이 가능하다.

그러나 루비는 언어 자체에서 인스턴스 변수에 접근 및 수정을 불가능하게 막아 놓았다.

이렇게 된 이유는 무엇이며, 어떻게 수정 및 호출을 해야하는걸까.





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
32
33
34
35
36
# python
class C(object):
    def __init__(self, v):
        self.value = v
    def show(self):
        print(self.value)
    def getValue(self):
        return self.value
    def setValue(self, v):
        self.value = v
c1 = C(10)
print(c1.getValue())
c1.setValue(20)
print(c1.getValue())
 
# ruby
class C
  def initialize(v)
    @value = v
  end
  def show()
    p @value
  end
  def getValue()
    return @value
  end
  def setValue(v)
    @value = v
  end
end
c1 = C.new(10)
# p c1.value
p c1.getValue()
# c1.value = 20
c1.setValue(20)
p c1.getValue()
cs


다른 객체지향 언어, 예를 들어 자바에서 사용하듯이 setter/getter 메소드를 사용해야한다.

setter는 변수를 setting하는 함수이며, getter는 변수를 가져오는 함수이다.

이는 임의로 변수로 접근하여 수정을 할 경우 자체적으로 assertion이 실행되는 특징이 있다.

이 때문에 좀 더 오류의 가능성이 적어지며 효율적인 코드 작성이 가능해진다.


setter나 getter 함수는 어떠한 이름을 사용해도 상관이 없으나

일반적으로 set변수이름/get변수이름 으로 사용하게 된다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# python
class Cal(object):
    def __init__(self, v1, v2):
        if isinstance(v1, int):
            self.v1 = v1
        if isinstance(v2, int):
            self.v2 = v2
    def add(self):
        return self.v1+self.v2
    def subtract(self):
        return self.v1-self.v2
    def setV1(self, v):
        if isinstance(v, int):
            self.v1 = v
    def getV1(self):
        return self.v1
c1 = Cal(10,10)
print(c1.add())
print(c1.subtract())
c1.setV1('one')
c1.v2 = 30
print(c1.add())
print(c1.subtract())
 
cs


위의 코드는 파이썬에 대한 예제이다.

파이썬에서는 isinstance(변수, 데이터형)으로 변수의 설정을 규제할 수 있다.

즉, 생성자의 데이터 값을 검증하는 것이다.

이를 assertion 과정이라고 하며 다른 데이터형으로 바뀌어 오류가 생기는것을 방지할 수 있다.

set 메소드도 마찬가지로 이렇게 데이터 형을 판단한뒤 인스턴스 변수를 변경하게 된다.


파이썬은 setter/getter 함수와 함께 데이터에 직접 접근하는 것을 막지 못한다.

따라서 이와같은 활용 방법은 권장되는 사항이지만 반드시 사용하는게 좋다.

기능이 좋은 IDE의 경우에는 객체 생성시 set/get이 자동으로 생성된다.





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
#ruby
class Cal
  attr_reader :v1, :v2
  attr_writer :v1
  def initialize(v1,v2)
    @v1 = v1
    @v2 = v2
  end
  def add()
    return @v1+@v2
  end
  def subtract()
    return @v1-@v2
  end
  def setV1(v)
    if v.is_a?(Integer)
      @v1 = v
    end
  end
  def getV1()
    return @v1
  end
end
c1 = Cal.new(10,10)
p c1.add()
p c1.subtract()
c1.setV1('one')
c1.v1 = 20
p c1.add()
c1.getV1()
cs


다음은 루비로 넘어가서 예제코드를 살펴보자

변수.is_a?(데이터형) 의 형식으로 assertion이 가능하다.

만약 setter 함수에 옳지 못한 데이터형이 들어 올 경우 인스턴스 변수 변경이 무시된다.


루비는 setter/getter를 사용하지 않는 경우는 변수에 대한 호출이나 변경이 불가능하다.

예를 들어 getter만 제공한 경우에는 인스턴스 변수에 대한 변경이 불가능하게된다.

이는 루비가 파이썬보다 변수에 대한 정책이 엄격하기 때문이다.




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
# python
class C(object):
    def __init__(self, v):
        self.__value = v
    def show(self):
        print(self.__value)
c1 = C(10)
#print(c1.__value)
c1.show()
 
# ruby
class C
  #attr_reader :value
  #attr_writer :value
  attr_accessor :value
  def initialize(v)
    @value = v
  end
  def show()
    p @value
  end
end
c1 = C.new(10)
p c1.value
c1.value = 20
p c1.value
cs


그렇다면 파이썬에서는 어떻게 인스턴스 변수에 접근을 못하게 막을수 있을까?

반대로 루비에서는 어떻게 인스턴스 변수에 접근을 할 수 있을까?


파이썬에서는 변수의 이름앞에 __를 붙여주면 된다.

__는 _(언더바)가 2개 붙어있는 형태이다.

이렇게 언더바가 2개 붙어지면 외부에서 접근할수 없는 변수가 된다. 


위의 루비 코드에서 attr_reader는 변수를 읽기 가능으로 설정하는 키워드이다.

또한, attr_write는 변수를 쓰기 가능으로 설정하는 키워드이다.

마지막으로  수정/삭제가 가능해진다.


이렇게 외부에서 접근이 가능한 변수를 파이썬에서는 property, 루비에서는 attribute라고 한다.



출처 : 생활코딩, 파이썬&루비

저작자 표시
신고

자바스크립트(Java Script)



(웹 프로그래밍 3대장 - 아카이누 키자루 아오키지)



앞선 포스팅에서 살펴본 HTML에서 말했듯이, 자바스크립트는 동적 페이지 구현을 위한 언어이다.

버튼 클릭시 이벤트의 상세한 구현이나 서버와의 통신이 대부분 자바 스크립트로 이루어진다.

자바스크립트는 이름에서도 알수 있듯이 스크립트 언어로써, 인터넷 브라우저의 스크립트 엔진으로 돌아가게 된다.


이름부터 자바와 비슷한 자바스크립트는 자바와 아무런 관련이 없다.

브랜던 아이크라는 사람이 10일만에 설계한 언어로써, 초기에 이름을 몇번씩 바꾸면서 

'Java와 구문의 유사성이 있으므로 Java Script라는 이름으로 최종결정되었다'

라고 하지만 대외적으로 알려진것은 역시 그 당시 뜨거웠던 자바의 인기에 어느정도 편승하기 위한 전략이었다.

확실히 구문이 비슷하게 느껴지는것은 두 언어다 C언어에서 영감을 받아 제작된 C-family 언어이기 때문이다.

이러한 전략은 자바의 짝퉁 느낌을 물씬 풍기며, 초기에 개발자들로 부터 무시 받기도 했다.


그러나 자바스크립트의 막강한 기능으로 점점 주목받기 시작했고,

MS에서 이를 채택하고 제 1차 브라우저 전쟁에서 승리하면서 자바스크립트는 메이저 언어로 떠올랐다.

(90년대 초, 당시 대부분의 브라우저 점유율을 차지하고 있었던 넷스케이프와 MS의 익스플로러가

한바탕 전쟁을 치루고 결국 익스플로러가 이긴것이 1차 브라우저 전쟁이다.

MS의 전략은 모든 윈도우 컴퓨터에 기본적으로 익스플로러를 깔아서 출시하는 것이였다. 그러니 이길수 밖에)

또한 2000년대 초반에 AJAX 기능이 추가되며, 페이지의 새로고침없이 데이터를 받아올 수 있게되면서 상당히 강력해졌다.





(자바스크립트의 대가 - 더글라스 크락포드)


자바스크립트의 특징은 명령형, 함수형, 객체지향형 언어라는 것이다.

간단하고 유연하기 때문에 초보자가 배우기 쉽기때문에 많은 프로그래밍 부트캠프에서 가르치는 언어 중 하나이다.

그러나 배우면 배울수록 터지는 매력에 끝을 알수 없는 언어이기도 하다.

물론 유행의 주기가 짧게 계속 생성되는 프레임워크도 이에 한몫하는 요소 중의 하나이다.

다른 특징중에 하나는 비동기 싱글 스레드로 동작한다는 것이다.

이러한 특징을 잘 알아야 효율적인 프로그래밍이 가능하다. 


대표적인 라이브러리, 프레임워크는 JQuery, Angular, React, Vue 등이 있으며

백엔드에서는 자바스크립트 기반 런타임 환경인 Node JS 가 각광받고 있다.


현재는 ES6, ES7 등의 표준안이 계속해서 나오고 있고, 이 때마다 문법적으로 추가되는 요소가 많아서 끝없이 배워야한다.

또한 많은 브라우저가 이러한 표준안을 지원하지 않으므로 ES5로 변환하는 babel을 사용해야한다.

요새 계속해서 보완되고 바뀌고, 라이브러리와 프레임워크가 쏟아져 나오며, 기본 개념도 놓쳐선 안되니

진짜 끝임없이 배워야한다. 


결론적으로 자바스크립트는 진입장벽이 낮지만, 여러가지 이유로 복잡하고 가끔은 변태적인 언어이기도 하다.

그만큼 매력이 넘치는 요소도 많으니 한 포스팅에서 모든것을 설명하기는 어렵다.

자바스크립트의 대가인 더글라스 크락포드가 문법적 특징과 권고안을 잘 설명해놓았으니

자바스크립트를 사용한다면 반드시 그의 저서를 참고하기 바란다.



저작자 표시
신고

객체(Object)



객체 지향 프로그래밍(Object Oriented Programming)이라는 말에서도 알수 있듯이

객체는 OOP의 기반이 되는 개념중의 하나이다.


함수만 묶어 놓았던 모듈과는 다르게, 객체에서는 변수와 함수를 묶어서 찍어낼수 있는 개념이다.

이렇게 객체를 기반으로 생성된 것을 인스턴스라고한다.

여기서는 객체에 대한 개념을 깊게 다루지는 않을 것이며, 사용 방법에 대해 알아보도록하겠다.





1
2
3
4
5
6
7
8
# python
class Cal(object):
   # 클래스 코드
 
#ruby
class Cal
   # 클래스 코드
end
cs


먼저 class 키워드를 사용해서 객체를 만들어 준다.

이때, 루비는 역시 end 키워드를 사용해서 객체 생성 코드를 닫아주며,

파이썬은 class뒤에 객체이름(object):를 적어 준다.





1
2
3
4
5
6
7
8
9
10
11
# python
class Cal(object):
    def __init__(self, v1, v2):
        print(v1, v2)
 
#ruby
class Cal
  def initialize(v1,v2)
    p v1, v2
  end
end
cs


객체를 생성할 때 내부에 생성자를 만들어준다.

생성자라는 것은 객체로 부터 인스턴스가 만들어질때 자동으로 실행되는 메소드를 생성자라고한다.

이 생성자의 이름은 미리 약속되어있으므로, 해당 이름으로 사용해야한다.

파이썬은 __init__이며, 루비는 initialize이다.


따라서, 이 생성자에 원하는 코드를 작성해 놓으면 인스턴스가 생성될 때 자동으로 실행된다.

위의 코드에서 파이썬과 루비의 생성자는 v1, v2를 출력하게 설정했다. 

다른점은, 파이썬은 생성자를 만들때 첫번째 인자로 self를 넣어주어야 한다는 것이다.

이 self에 대한 내용은 아래의 파이썬 코드에서 설명하도록 하겠다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Cal
  def initialize(v1,v2)
    @v1 = v1
    @v2 = v2
  end
  def add()
    return @v1+@v2
  end
  def subtract()
    return @v1-@v2
  end
end
c1 = Cal.new(10,10)
p c1.add()
p c1.subtract()
c2 = Cal.new(30,20)
p c2.add()
p c2.subtract()
 
cs


최종적으로 완성된 객체와, 인스턴스 생성, 메소드 사용 코드이다.

위의 코드는 루비로 작성되었다.


먼저, 생성자가 실행될 때 인자로 받아온 2개의 값을 인스턴스 변수에 저장하게된다.

인스턴스 변수를 사용하기 위해서는 변수 이름앞에 @ 기호를 붙여주자.

이렇게 인스턴스 변수가 따로 있기 때문에 모든 인스턴스가 같은 객체로부터 생성되었더라도 다른 값을 가질수 있다.

그리고 내부에 더하기, 빼기 메소드를 만들어준다.


이렇게 생성된 객체를 인스턴스화 하기 위해서는 '객체이름.new(인자)'의 형식으로 만들수 있다.

또한 '인스턴스.메소드이름'의 형식으로 메소드 호출이 가능하다.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Cal(object):
    def __init__(self, v1, v2):
        self.v1 = v1
        self.v2 = v2
 
    def add(self):
        return self.v1+self.v2
 
    def subtract(self):
        return self.v1-self.v2
 
 
c1 = Cal(10,10)
print(c1.add())
print(c1.subtract())
c2 = Cal(30,20)
print(c2.add())
print(c2.subtract())
cs


이번에는 같은 기능을 하는 파이썬 예제이다.

이 때 루비에서 사용하는 @를 사용할수 없고 self를 사용해야되는데,

파이썬에서 사용하는 모든 메소드에서는 첫번째 매개변수로 self를 적용해야한다.

이 self는 해당 인스턴스를 가리키는 값이다. 타 언어의 this라고 생각해도 좋을듯하다.


따라서, 이 첫번째 매개변수로 해당 인스턴스의 변수를 사용하거나 지정 수 있다.

물론 이 self 인자는 다른 이름으로 바꾸어도 되지만 관습적으로 self라고 사용한다.



출처 : 생활코딩, 파이썬&루비


저작자 표시
신고

+ Recent posts

티스토리 툴바