클래스 변수

  • C++/Java에서 static 멤버 변수와 같은 역할
  • 정의 방법
    class ClassName1:
      var1 = None
      ...
    
  • 사용 방법 : [클래스명].[변수명], [인스턴스명].[변수명] 모두 가능


인스턴스 변수

  • C++/Java에서 비 static 멤버 변수와 같은 역할
  • 정의 방법
    class ClassName2:
      def __init__(self):
        self.var2 = None
        ...
    
  • 사용 방법 : [인스턴스명].[변수명] 만 가능
  • 같은 이름일 경우, 인스턴스 변수에서 먼저 찾고 클래스 변수에서 찾는다


<테스트 환경> 
- OS : Windows 10 
- Python 버전 : 3.7.5
,
현재의 티스토리 에디터는 직접 markdown 편집도 지원을 하고 있지만, 구 버전의 편집기 사용시에 다음과 같은 markdown 소스를 작성하여 HTML 변환을 한 후 티스토리 소스에 붙여넣을 경우,


## 제목1
본문

## 제목2
- 리스트1
- 리스트2

본문

## 제목2
본문

- 리스트1
- 리스트2


아래와 같이 깔끔하지 않게 나오지 않는 경우가 있는데, (특히, 단락 앞뒤에 공백 옵션을 사용하지 않았을 경우. 적용되는 스킨의 CSS에 따라 차이는 있을 수 있음.)


제목1

본문

제목2

  • 리스트1
  • 리스트2

본문

제목2

본문

  • 리스트1
  • 리스트2


이 변환기를 사용할 경우, 다음과 같이 추가적인 줄바꿈을 넣어줘서,


## 제목1
<p><br></p>
본문
 
<p><br></p>
<p><br></p>
## 제목2
- 리스트1
- 리스트2
 
본문
 
<p><br></p>
<p><br></p>
## 제목2
<p><br></p>
본문
 
- 리스트1
- 리스트2


HTML 변환후에, 아래 결과와 같이 보기좋게(?) 표시될 수 있게합니다.


제목1


본문



제목2

  • 리스트1
  • 리스트2

본문



제목2


본문

  • 리스트1
  • 리스트2


변환기 소스


md_convert.py:

# -*- coding: utf-8 -*-
#!/usr/bin/python

import sys

DOUBLE_BR_BEFORE_HEADER = True

STATUS_START = 0
STATUS_NONE = 1
STATUS_LIST = 2
STATUS_PRE = 3
STATUS_HEADER = 4

LINE_BR = "<p><br></p>\n"

def print_usage():
    print("usage: python md_convert.py [option]")
    print("Options:")
    print("-i input-file : 지정된 입력 파일을 사용하여 변환을 하고 입력 파일을 덮어씁니다.")
    print("-i input-file output-file : 지정된 입력 파일과 출력 파일을 사용하여 변환을 합니다.")

def is_ol_item(str):
    pos = str.find(". ")
    if pos == -1:
        return False
    return str[:pos].isdigit()

def go_convert(config):
    filename_in = config["filename_in"]
    filename_out = config["filename_in"]
    if "filename_out" in config:
        filename_out = config["filename_out"]

    print("\nconverting %s.." % filename_in)

    file_in = open(filename_in, 'r', encoding = "utf-8")

    all_line = []
    for line in file_in:
        all_line.append(line)
    file_in.close()

    all_line_new = []
    insidePre = False
    status = STATUS_START
    status_old = status

    for line in all_line:
        status_old = status

        line_strip = line.lstrip()
        if len(line_strip) > 0:
            if insidePre:
                if line_strip[:5] == "</pre":
                    insidePre = False
            else:
                if line_strip[:4] == "<pre":
                    insidePre = True
                    status = STATUS_PRE
                elif line_strip[:1] == "-" or is_ol_item(line_strip):
                    status = STATUS_LIST
                elif line_strip[:1] == "#":
                    status = STATUS_HEADER
                else:
                    status = STATUS_NONE
                    
            if DOUBLE_BR_BEFORE_HEADER and status == STATUS_HEADER and status_old != STATUS_START:
                all_line_new.append(LINE_BR)
                
            if status_old == STATUS_NONE:
                if status == STATUS_HEADER:
                    all_line_new.append(LINE_BR)
            elif status_old == STATUS_HEADER:
                if status == STATUS_NONE:
                    all_line_new.append(LINE_BR)
                if status == STATUS_HEADER:
                    all_line_new.append(LINE_BR)
        all_line_new.append(line)

    file_out = open(filename_out, 'w', encoding = "utf-8")
    for line in all_line_new:
        file_out.write(line)
    file_out.close()

    print("end")

config = {}

if len(sys.argv) >= 2:
    if sys.argv[1] == "-i":
        if len(sys.argv) == 3:
            config['filename_in'] = sys.argv[2]
            go_convert(config)
        else:
            config['filename_in'] = sys.argv[2]
            config['filename_out'] = sys.argv[3]
            go_convert(config)
    else:
        print_usage()
else:
    print_usage()






사용 방법


사용 방법: python md_convert.py [옵션]
옵션:
-i input-file             : 지정된 입력 파일을 사용하여 변환을 하고 입력 파일을 덮어씁니다.
-i input-file output-file : 지정된 입력 파일과 출력 파일을 사용하여 변환을 합니다.


PS1. pre 태그 내에서 소스 코드에 html 관련 코드를 사용할 경우, 충돌이 나서 (특히 pre 태그 관련, 당연한가?) 소스내 모든 <와 >를 &lt;와 &gt;로 바꿔줄 수 밖에 없었습니다.
PS2. 추가 작업 후보 : 소스 md에 줄바꿈이 있을 때만 추가적인 줄바꿈 삽입
,

PyMunk에 pyGame을 결합한 예제 코드입니다.

우선 pyGame 기본 예제는 아래 글을 참고하시기 바랍니다.

>> pyGame 기본 예제

 

사전 설치 요구사항

pygame 모듈 사용시, 추가적인 pygame 모듈 설치를 필요로 합니다.

pip install pygame

 

예제 코드

import pygame
from pygame.locals import *
import pymunk
import pymunk.pygame_util

SCREEN_WD = 400
SCREEN_HT = 400
TARGET_FPS = 60

screen = pygame.display.set_mode((SCREEN_WD, SCREEN_HT), 0, 32)
pygame.display.set_caption("PyMunk_Example")
clock = pygame.time.Clock()

space = pymunk.Space()
space.gravity = 0, -1000
draw_options = pymunk.pygame_util.DrawOptions(screen)

ground = pymunk.Body(body_type=pymunk.Body.STATIC)
ground.position = 50, 50
 
ground_shape = pymunk.Segment(ground, (-50, 0), (50, 0), 1)
space.add(ground_shape)

body = pymunk.Body(1, 1666)
body.position = 50, 100
 
poly = pymunk.Poly.create_box(body, (10, 10))
space.add(body, poly)

timeStep = 1.0 / 60

running = True
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
            continue
        if event.type == KEYDOWN and event.key == K_ESCAPE:
            running = False
            continue

    screen.fill((0, 0, 0, 0))

    space.debug_draw(draw_options)

    space.step(timeStep)

    pygame.display.flip()
    clock.tick(TARGET_FPS)

pygame.quit()
print("done")

PyMunk에서는 다음 두 호출을 통해 기본적인 내용을 자동적으로 pyGame 영역에 그려주게 됩니다. 다만 (0, 0)에서부터 그려주므로 앞의 예제에서 전체적으로 (+50, +50) 만큼 좌표를 이동시켰습니다.

draw_options = pymunk.pygame_util.DrawOptions(screen)
...

space.debug_draw(draw_options)

 

정찰 위성 이미지

 

<테스트 환경>
  - OS : Windows 7
 - Python 버전 : 3.6
 - Pymunk 버전 : 5.3.2
 - PyGame 버전 : 1.9.3

 

,

파이썬용 2D 물리엔진중 하나인 Pymunk에 관한 기본 예제 코드를 소개하고자 합니다.



사전 설치 요구사항


pymunk 모듈 사용시, 추가적인 pymunk 모듈 설치를 필요로 합니다.

pip install pymunk


기본 예제


(0, 50) 좌표에 위치한 박스가 중력에 의해 지면을 향해 떨어져 지면에 부딧혀 멈출 때까지의 박스의 좌표가 출력되는(무려 텍스트로!) 예제 코드입니다. Pymunk 자체에는 그래픽 표현 기능이 없으므로 좌표 계산만 해줍니다. 이것을 화면 상으로 표현하는 것은 이후의 예제를 통하여 알아보겠습니다.

# -*- coding: utf-8 -*-

import pymunk

# 시뮬레이션 공간을 생성하고, 중력의 방향 및 크기를 설정한다.
space = pymunk.Space()
space.gravity = 0, -1000

# 두 점을 있는 직선을 나타내는 Segment 요소를 사용하여 지면을 생성한다.
# 길이 100, 두께 1인 직선을 생성하여 (0, 0)에 위치시킨다.
ground = pymunk.Body(body_type=pymunk.Body.STATIC)
ground.position = 0, 0
 
ground_shape = pymunk.Segment(ground, (-50, 0), (50, 0), 1)
space.add(ground_shape)

# (0, 50) 위치에 (10, 10) 크기의 박스를 생성한다.
body = pymunk.Body(1, 1666)  # 질량, 모멘트를 지정한다.
body.position = 0, 50
 
poly = pymunk.Poly.create_box(body, (10, 10))
space.add(body, poly)

# 1초 동안 1.0 / 60 초씩 진행시키며 박스의 좌표를 출력한다.
for i in range(60):
    space.step(1.0 / 60)
    print(body.position)


결과 캡처

Vec2d(0.0, 50.0)
Vec2d(0.0, 49.72222222222222)
Vec2d(0.0, 49.166666666666664)
Vec2d(0.0, 48.33333333333333)
Vec2d(0.0, 47.222222222222214)
Vec2d(0.0, 45.83333333333333)
Vec2d(0.0, 44.166666666666664)
Vec2d(0.0, 42.22222222222222)
Vec2d(0.0, 40.0)
Vec2d(0.0, 37.5)
Vec2d(0.0, 34.72222222222222)
Vec2d(0.0, 31.666666666666664)
Vec2d(0.0, 28.333333333333332)
Vec2d(0.0, 24.72222222222222)
Vec2d(0.0, 20.833333333333332)
Vec2d(0.0, 16.666666666666664)
Vec2d(0.0, 12.222222222222221)
Vec2d(0.0, 7.5)
Vec2d(0.0, 2.5)
Vec2d(0.0, 2.886956552845999)
Vec2d(0.0, 3.2330661044876274)
Vec2d(0.0, 3.542236920798546)
Vec2d(0.0, 3.8179830207826186)
Vec2d(0.0, 4.065083408185165)
Vec2d(0.0, 4.286249625299963)
Vec2d(0.0, 4.483745226989828)
Vec2d(0.0, 4.659603964972919)
Vec2d(0.0, 4.81565131414432)
Vec2d(0.0, 4.95352387113101)
Vec2d(0.0, 5.074686834357406)
Vec2d(0.0, 5.180449754301324)
Vec2d(0.0, 5.273414633437768)
Vec2d(0.0, 5.356441970464741)
Vec2d(0.0, 5.431683496733098)
Vec2d(0.0, 5.500322361070223)
Vec2d(0.0, 5.562826033647434)
Vec2d(0.0, 5.619373494273605)
Vec2d(0.0, 5.670188929782226)
Vec2d(0.0, 5.7156761612570905)
Vec2d(0.0, 5.756385891638544)
Vec2d(0.0, 5.792908604984999)
Vec2d(0.0, 5.822032616838716)
Vec2d(0.0, 5.844112775433398)
Vec2d(0.0, 5.859454641289297)
Vec2d(0.0, 5.868318121528639)
Vec2d(0.0, 5.870920746762018)
Vec2d(0.0, 5.86744062807873)
Vec2d(0.0, 5.858019128912104)
Vec2d(0.0, 5.897059737778078)
Vec2d(0.0, 5.925671363059304)
Vec2d(0.0, 5.909019468605577)
Vec2d(0.0, 5.9310174562872575)
Vec2d(0.0, 5.94492949182134)
Vec2d(0.0, 5.953966287149509)
Vec2d(0.0, 5.958854474347584)
Vec2d(0.0, 5.959613136913926)
Vec2d(0.0, 5.961507841637967)
Vec2d(0.0, 5.964013945366503)
Vec2d(0.0, 5.9657250791899505)
Vec2d(0.0, 5.966229061776563)


참고 자료

<테스트 환경> 
- OS : Windows 7 
- Python 버전 : 3.6
- Pymunk 버전 : 5.3.2
,

파이썬에서 문자열은 바이트 코드와 유니코드로 나뉜다.


파이썬 3에서,

바이트 코드의 타입 -> <class 'bytes'>

유니 코드의 타입 -> <type 'str'>



변환


바이트 코드는 euc-kr, UTF–8 등과 같이 특정 인코딩이 적용된 문자열을 말한다. 파이썬에서 유니코드는 어떤 특정 인코딩에 속하지 않는 유니버셜한 어떤 것을 나타낸다. (다른 언어에서 흔히 UTF–8을 유니코드로 일컫는 것과는 다름에 유의)

  • 유니코드 >>> 바이트 코드로 변환하기 위해서는 encode() 함수가 사용된다.

  • 바이트 코드 >>> 유니코드로 변환하기 위해서는 decode() 함수가 사용된다.

    bstr = str.encode("UTF–8") # 유니코드에서 UTF–8 바이트 코드로 변환 
    str = bstr.decode("UTF–8") # UTF–8 바이트 코드에서 유니코드로 변환


타입 확인

  • type() 함수를 사용하여 어떤 문자열이 유니코드인지 바이트 코드인지 알아낼 수 있다.
    print(type(bstr)) # 바이트 코드일 경우 
    -> <type 'bytes'> 
    
    print(type(str)) # 유니코드일 경우
    -> <type 'str'>


소스 코드 상에서 대입시,


파이썬 2에서는 기본적으로 바이트 코드이고 <type 'str'>로 표기되며, 이에 대비되는 유니코드가 있는 것과 달리,

파이썬 3에서는 기본적으로 유니코드이고 <type 'str'>로 표기된다.


참고


print 함수를 사용하여 바이트 코드를 출력할 경우, 앞에 b'가 붙는 것을 볼 수 있다.


테스트 환경 
- OS : Windows 7 
- Python 버전 : 3.6


,
외부 프로그램을 실행하고 그 표준 출력/에러를 텍스트 컨트롤에 표시하는 어플의 Template입니다.


template2.py
# -*- coding: utf-8 -*-
#!/usr/bin/python
 
import wx
import subprocess
import threading
import sys
 
COMMAND_PATH = "test.py" # 실행할 외부 프로그램 경로

def stdout_thread(pipe, callback):
    for line in iter(pipe.stdout.readline, b''):
        callback(line.rstrip())

def exec_command(cmd, callback, cwd=None):
    p = subprocess.Popen(cmd, 
                         stdout=subprocess.PIPE, 
                         stderr=subprocess.STDOUT, cwd=cwd)
    out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p, callback))

    out_thread.start()
 
class MainWindow(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size = (480, 320),
            style = wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
             
        vbox = wx.BoxSizer(wx.VERTICAL)

        self.tc = wx.TextCtrl(self, 1, size = (-1, 200), style = wx.TE_MULTILINE)
        vbox.Add(self.tc, 0, wx.EXPAND | wx.ALL)

        self.SetSizer(vbox, True)
        self.Layout()
         
def callback_stdout(msg):
    print("}}} " + msg)
    frame.tc.AppendText(msg + "\n")
             
app = wx.App(False)
frame = MainWindow(None, -1, u"Title")
frame.Show(1)

exec_command([sys.executable, COMMAND_PATH], callback_stdout)

app.MainLoop()


test.py
# -*- coding: utf-8 -*-
#!/usr/bin/python

import sys

print "blah;blah;"
sys.stdout.flush()


[주의사항] 실행하려는 외부 프로그램이 python 코드일 때, 외부 프로그램에서 메세지 출력 후 sys.stdout.flush()를 해줘야 메세지가 그때 그때 출력된다. 그렇지 않으면 메세지가 마지막에 한꺼번에 출력된다.


template2.py 실행 화면


 


<테스트 환경>
OS : Windows 7
Python 버전 : 2.7
wxPython 버전 : 2.8.12.1


,

파이썬에서 문자열은 바이트 코드와 유니코드로 나뉜다.


바이트 코드는 euc-kr, UTF–8 등과 같이 특정 인코딩이 적용된 문자열을 말한다. 파이썬에서 유니코드는 어떤 특정 인코딩에 속하지 않는 유니버셜한 어떤 것을 나타낸다. (다른 언어에서 흔히 UTF–8을 유니코드로 일컫는 것과는 다름에 유의)

  • 유니코드 >>> 바이트 코드로 변환하기 위해서는 encode() 함수가 사용된다.

  • 바이트 코드 >>> 유니코드로 변환하기 위해서는 decode() 함수가 사용된다.

    str = ustr.encode("UTF–8") # 유니코드에서 UTF–8 바이트 코드로 변환 ustr = str.decode("UTF–8") # UTF–8 바이트 코드에서 유니코드로 변환

  • type() 함수를 사용하여 어떤 문자열이 유니코드인지 바이트 코드인지 알아낼 수 있다.

    print type(str) # 바이트 코드일 경우
    -> <type 'str'>
    
    print type(ustr) # 유니코드일 경우
    -> <type 'unicode'>
    


소스 코드 상에서 대입시,


[1]

# -*- coding: utf-8 -*-

myStr = "가나다"

myStr의 타입 -> utf-8의 <type 'str'>

[2]

# -*- coding: cp949 -*-

myStr = "가나다"

myStr의 타입 -> cp949의 <type 'str'>

[3]

myStr = u"가나다"

myStr의 타입 -> <type 'unicode'>

'# -*- coding: ~' 을 붙이지 않을 경우, 시스템 로케일인 cp949의 <type 'str'>로 적용되어야 할 것 같은데, 실제 테스트 결과는 utf-8로 적용된다??


[참고] 이것은 파이썬 2.X 대에서 적용되는 내용이고, 파이썬 3.X 대에서는 방식이 약간 달라지게 되는데...


테스트 환경
- OS : Windows 7
- Python 버전 : 2.7


,

사전 설치 요구사항


Beautiful Soup 모듈 사용시, 추가적인 Beautiful Soup 모듈 설치를 필요로 한다.

pip install bs4


HTML 파싱 예제

# -*- coding: utf-8 -*-
 
from bs4 import BeautifulSoup
import requests
 
# request 모듈을 사용하여 웹 페이지의 내용을 가져온다
url = 'http://httpbin.org'
r = requests.get(url)
 
 
# beautiful soup 초기화
soup = BeautifulSoup(r.text, "html.parser")
 
# 태그로 찾기 (첫번째 항목)
mr = soup.find("a")
print mr.get_text() # get_text() 함수는 도큐먼트 혹은 특정 태그 밑에 있는 모든 텍스트를 추출한다
print mr.string
 
# 태그로 찾기 (모든 항목)
mr = soup.find_all("a")
print mr[0]
 
# id로 찾기
mr = soup.find(id="AUTHOR")
print mr.get_text()
 
# class로 찾기
mr = soup.find(class_="bash")
print mr.get_text()
mr = soup.find("code", class_="bash") # id와 class를 조합하여 찾을 수도 있다
print mr.get_text()
 
# 찾기 결과에 대해 다시 한번 찾기를 수행할 수 있다
tables = soup.find("ul")
mr = tables.find("li")
print mr


테스트 환경
 - OS : Windows 7
 - Python 버전 : 2.7


,