3월 24, 2024

파이썬으로 스누피 캐릭터 그리기 투토리얼

1. Python turtle library를 사용하여 스누피 그리기

파이썬 turtle library를 사용하면 다양한 기능을 사용하여 원하는 것을 그릴 수 있다.

이전에도 python turtle library를 사용하여 어피치, 라이언, 보노보노 등 다양한 캐릭터를 그리는 방법을 영상으로 제작한 바 있는데, 오늘은 스누피 캐릭터 그리는 방법에 대한 투토리얼을 제작했다.

 

1) 링크

 https://youtu.be/svN8Q-Acnpo


해당 방법은 위의 동영상을 참고해주면 된다. 

 

스누피는 이전 캐릭터와 달리 굴곡을 구현하는 것이 어렵기 때문에 조금 더 섬세한 조정이 필요하다.


2) python으로 현재 좌표값 찾기

https://www.programmingstory.com/2024/02/python-turtle.html

가장 유용하게 사용했던 문법은 현재 좌표를 구할 때 사용하던 xcor, ycor 문법이었으며, 자세한 내용은 이전 글을 참고해주면 된다. 


3월 19, 2024

enumerate란? index와 원소를 동시에 알 수 있는 내장함수

1. Python for문

for문을 돌릴 때 가장 기본이 되는 구조는 아래와 같다. 


a=[10, 11, 12, 13]
for index in range(4):
	print(index)
#result
#0
#1
#2
#3


a라는 list에서 range(4) 라고 하여 for문을 돌리면

0부터 4까지 하여 0 1 2 3이 출력된다. (또는 len() 함수를 사용해도 된다

 

만약 0, 1, 2, 3번에 해당되는 list의 숫자를 출력하고 싶다면 아래와 같이 적으면 된다.


a=[10, 11, 12, 13]
for index in range(4):
	print(a[index])
    
 #result
 #10
 #11
 #12
 #13

index번째에 있는 리스트의 숫자를 출력하라는 뜻이고,

각각 0번째, 1번째, 2번째, 3번째 수를 출력하여 결과적으로 10, 11, 12, 13이라는 값이 출력되게 된다. 


2. enumerate() 


여기서 그러면 list의 index와 index에 해당되는 숫자를 동시에 받아올 수 있는 방법은 없을까라는 생각이 들 수 있다.

그럴 때 바로 enumerate()라는 함수를 사용하면 되는 것이다. 

a=[10, 11, 12, 13]
for index, number in enumerate(a):
	print(index, number)
    
#result
#0 10
#1 11
#2 12
#3 13

파이썬에서 enumerate() 함수는 인덱스와 원소로 이루어진 tuple을 만들어 주는 함수이다.

index는 기본적으로 0으로부터 시작하게 된다.

 

위 코드에서 index가 말 그대로 list에서의 index를 의미하고, number는 해당 원소를 의미하게 된다. 이 두 변수명은 자신이 원하는 대로 설정해주면 된다.

 

따라서 위 코드를 실행하면

0 10

1 11

2 12

3 13

 

이런 식으로 출력되게 되는 것이다. 

 

생각보다 파이썬에서 for문을 돌리면서 인덱스와 원소를 함께 알아오면 편한 경우가 많기 때문에

enumerate()함수를 잘 알아두면 매우 편리할 것이다. 


2월 19, 2024

Django secret key 관리하기

https://www.programmingstory.com/2024/02/django-diary-6-crud-delete.html

지난 포스팅에서 간단한 Diary web을 만들었고 이를 git에 올렸더니 위와 같은 경고 메세지가 떴다. 


즉 내가 만든 github repository가 위험이 있다는 것이다. 즉 원래같으면 

GitGuardian에서 위와 같이 떠야 하는데, At risk가 떴다는 것은 무엇인가를 해결해야 한다는 뜻이다. 

자세히 에러 문구를 보면 위와 같이 open secret incident가 포함되어 있다고 나와있다. 에러 메세지를 더 클릭해보면 settings.py에서 SECRET_KEY가 포함되어 있고 이 secret_key는 비밀 값이기 때문에 프로젝트 코드에 포함되면 안되며, github에도 올리면 안된다. 

 

그래서 우리는 이러한 시크릿 키를 별도의 JSON 파일에 적어서 별도로 관리해주게 된다. 먼저 그럼 우리는 secrets.json 파일을 만들어주도록 하자.

 

secrets.json 파일을 만들고 아래와 같이 코드를 추가해주자.

{
    "SECRET_KEY": "<Django secret key>"
}

 

또는 settings.py에 원래 존재하던 secret_key 코드를 그대로 적어두어도 된다.

 

그리고 이제 settings.py에 들어가서 코드를 아래와 같이 수정해준다.

from pathlib import Path
import os
import json
from django.core.exceptions import ImproperlyConfigured

BASE_DIR = Path(__file__).resolve().parent.parent
ROOT_DIR = os.path.dirname(BASE_DIR)
secret_file = os.path.join(BASE_DIR, 'secrets.json') # secrets.json 파일 위치
with open(secret_file) as f:
    secrets = json.loads(f.read())

def get_secret(setting, secrets=secrets):
    try:
        return secrets[setting]
    except KeyError:
        error_msg = "Set the {} environment variable".format(setting)
        raise ImproperlyConfigured(error_msg)

SECRET_KEY = get_secret("SECRET_KEY")

 

그런 다음에 이를 secret key를 git에는 ignore 해주겠다는 뜻으로 .gitignore에 다음과 같이 추가해준다.

# .gitignore
secrets.json

이런식으로 수정해주면 secret key를 별도로 관리할 수 있게 되며, git에서도 secret incident라는 알림이 사라지는 것을 볼 수 있다. 


2월 17, 2024

[Django] diary 만들어보기 (4) CRUD 구현-Read

https://www.programmingstory.com/2024/02/django-diary-3-crud-create.html

포스팅이 계속해서 이어지고 있다. 저번 포스팅에서는 CRUD 중에서 Create를 알아보았고 이번에는 CRUD 중에서 Read를 알아보려고 한다. 


Read를 하는 과정을 생각해보면, 

먼저 일기를 클릭하면 post/일기아이디/ url로 이동하여서 일기 페이지를 보여주어야 할 것이다. 그러기 위해서 먼저 urls.py부터 추가를 해보자. 


from django.urls import path
from diary import views

app_name='diary'
urlpatterns = [
    path('', views.index, name='index'),
    path('create/', views.create, name='create'), 
    path('<int:id>/', views.show, name='show'), # add this line
]


하지만 여기까지 썼다면 당연히 에러가 날 것이다. 왜냐하면 우리는 아직 views.show 함수를 만들지 않았기 때문이다. 그러면 이제 views.show를 만들러 views.py에 가보자

 

show 함수는 해당 아이디에 해당되는 일기를 보여주어야 하기 때문에 parameter로 추가적으로 id 값을 함께 가지게 된다.


def show(request, id):
    post = Post.objects.get(id=id)
    return render(request, 'diary/show.html', {'post':post})


이러면 show 함수는 diary/show.html로 render된다는 것을 알 수 있다. 그러면 순서대로 따라가, 우리는 show.html을 다시 만들어주어야 한다. 하던대로 이를 templates/diary/폴더 안에다가 생성해준다. 

 

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My diary</title>
  </head>
  <body>
    <div>
      <a href="{% url 'diary:index' %}">return</a>
      <h1>Title: {{ post.title }}</h1>
      <h3>Satisfaction: {{ post.satisfaction }}</h3>
      <p>Content: {{ post.content }}</p>
    </div>
  </body>
</html>


가장 위에는 홈 화면으로 돌아갈 수 있게 index url로 연결시켜줄 수 있는 return 버튼을 만들어주었고 그 다음에는 받은 post 객체에 대해 title, satisfaction, content 정보를 각각 출력할 수 있도록 코드를 작성했다. 

 

이런 식으로 한다면 

Title을 클릭하면 


이런식으로 Title, satisfaction, content가 보이는 페이지로 이동하고 위의 return을 누르면 다시 메인 화면으로 돌아오게 된다. 

 

다음 포스팅에서는 CRUD의 update를 다루어보도록 하겠다.


2월 17, 2024

[Django] diary 만들어보기 (3) CRUD 구현-Create

https://www.programmingstory.com/2024/02/django-diary-2-mtv-models-templates-view.html

전 포스팅에서는 MTV 패턴의 기본적인 골격을 잡아보는 연습을 했다. 이제는 diary에서 새로운 일기를 추가하고, 수정하고, 삭제하고 보여주는 것을 구현해볼 것이다. 

흔히 우리는 이것을 CRUD라고 하는데 (Create, Read, Update, Delete)의 약자이다. 


먼저 Create 부터 구현을 해보자.

Create을 하기 위해서는 post/create/라는 url로 이동하면 새로운 화면이 보여야 하고, 그러기 위해서는 urls.py 함수에 views.create으로 이동할 수 있게 views 함수도 수정을 해주어야 한다. 

 

먼저 그럼 diary/urls.py에 들어가서 url 경로부터 추가를 해주자. 

from django.urls import path
from diary import views

urlpatterns = [
    path('', views.index, name='index'), 
    path('create/', views.create, name='create'), # add this line
]


그리고 urlpatterns에도 써있듯이, 두 번째 인자로 views.create라는 함수를 필요로 함으로 views.py에 가서 create 함수를 만들어주자. 아래의 코드처럼 작성해주면 된다. 

#views.py
def create(request):
    return render(request, 'diary/create.html')

 

create 함수는 create.html 페이지로 render해주기 때문에 create.html 페이지를 새롭게 만들 필요가 있다. 미리 만들어놓은 templates/diary 폴더에 create.html 파일을 하나 만들어주고 새 일기를 추가할 때 화면을 작성해주면 된다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My diary</title>
  </head>
  <body>
    <h1>new diary</h1>
    <form action="{% url 'diary:index' %}" method="POST">
      {% csrf_token %}
      <p>title</p>
      <input name="title" /> <br />
      <p>Satisfaction</p>
      <input name="satisfaction" /> <br />
      <p>content</p>
      <textarea name="content" rows="30" cols="40"></textarea> <br />
      <input type="submit" value="submit" />
    </form>
  </body>
</html>

create.html에서 create한 정보를 다시 diary의 index url로 넘겨주는 것이고 그 방식이 POST가 되는 것이다. 새롭게 추가할 경우에 필드 값인 title, satisfaction, content 값을 input으로 받을 수 있도록 해 주었다. 

 

그러면 이제 index 함수에서 들어오는 method가 POST이냐 GET이냐에 따라서 상황을 다르게 처리해주어야 한다. 

그러므로, views.py에서 def index를 아래와 같이 수정해준다.

def index(request):
    if request.method == 'GET': # index
        posts = Post.objects.all()
        return render(request, 'diary/index.html', {'posts': posts})
    elif request.method == 'POST': # create
        title = request.POST['title']
        satisfaction = request.POST['satisfaction']
        content = request.POST['content']
        Post.objects.create(title=title, satisfaction=satisfaction, content=content)
        return redirect('diary:index') 

즉, 그냥 목록을 보여줄 때와 새롭게 create을 통해 POST할 경우를 분리하는 것이다. 

 

또한, 

Create을 하기 위해서는 추가를 할 수 있는 버튼이 필요하다. 버튼을 누르면 새로운 일기를 추가할 수 있는 페이지로 넘어가야 하기 때문에 index.html에 아래와 같이 수정을 해준다. 

<!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>My diary</title>
  </head>
  <body>
    <h1>Diary page</h1>
    <a href="/post/create">add</a>
    {%for post in posts%}
    <div style="border: 2px solid green;">
      <a href="/post/{{post.id}}">
        <h3> {{post.title}} </h3>
      </a>
      <h3> satisfied: {{post.satisfaction}} </h3>
      <h3> {{post.content}} </h3>
    </div>
    {% endfor %}
  </body>
</html>

<body> 뒤에 add 라는 링크를 걸어 준 것 이외에는 전 포스팅에서 다루었던 코드와 동일하다. 

 

이렇게 해주고 확인해보면,

이런 식으로 add 버튼이 새롭게 생겼고, add를 클릭해보면


위와 같이 화면이 잘 나오는 것을 알 수 있다. 이렇게 하면 새 일기를 만들어 줄 수 있다.

 

이제 CRUD 중에서 C를 구현했으니 다음 포스팅에서는 R (read)에 대해서 알아보도록 하겠다. 


2월 17, 2024

[Django] diary 만들어보기 (2) MTV 패턴 이란? models, templates, view 설정

https://www.programmingstory.com/2024/02/django-diary.html

우선 전 포스팅처럼 기본 설정을 한 뒤에 이어서 시작해보겠다. 


먼저 사용자에게 보여줄 화면을 만들어주어야 한다. 사용자에게 보여줄 화면은 template이 담당하고 있고 특히나 중요한 것은 django에서는 무조건 html 파일을 templates 라는 폴더 안에서 찾기 때문에 templates라는 폴더를 하나 만들어주자. 그리고 전 포스팅에서도 언급했듯이, django에서는 여러 개의 앱을 같이 만들 수 있기 때문에 diary 폴더의 templates 안에 diary라는 이름의 폴더를 하나 더 만들어주자. 그리고 그 폴더 안에 index.html 파일을 하나 만들어주자. 그런 다음에 index.html 파일 안에 간단히 적어보자

 

우선은 화면만 구상을 할 것이므로 간단하게만 아무거나 적어도 관계없다.

<!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>My diary</title>
  </head>
  <body>
    <h1>Diary page</h1>
  </body>
</html>

우선 위와 같이 title과 h1 정도만 적어주었다. 


그런 다음 terminal에 


python manage.py runserver


를 적어보자. 위 명령어는 실제로 화면이 어떻게 나오는지를 살펴보기 위해 runserver를 해보겠다는 뜻이다. 

 

그러면 


위와 같이 나올 텐데 위 그림에서 

 

빨간색으로 표시된 부분에 control을 누른 상태에서 클릭을 하면 인터넷 상에서 다음과 같은 창이 뜨는 것을 알 수 있을 것이다. 

우리가 html 페이지를 작성했지만 아직 아무것도 나오지 않는 것을 알 수 있다. html 페이지가 보이기 위해서는 html 페이지를 보여달라고 요청하는 views.py가 필요하다.

 

따라서 diary/views.py에 들어가서 아래와 같이 index 함수를 작성해보자.


from django.shortcuts import render

# Create your views here.
def index(request):
    return render(request, 'diary/index.html')

 

다음으로 url 부분을 작성해주어야 한다. diary_project/urls.py에 들어가서 아래와 같이 코드를 수정해주자.


from django.contrib import admin
from django.urls import path
import diary.views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', diary.views.index, name='index')
]


즉 diary.views를 import 해주고 path를 하나 더 추가해준것이다. ' ' 라는 것은 기본 경로 (localhost:8000/) 로 url이 들어올 시에 두 번째 인자로 들어온 함수를 실행시켜주겠다는 것이다. 즉 만약 localhost:8000/ 로 들어오면 diary.views.index 함수를 실행시켜주는 것이고 diary.views.index 함수는 index.html 페이지를 render하고 있으니 index.html 페이지가 보이게 되는 것이다. 

 

이렇게 하고 terminal에 python manage.py runserver를 입력하면,


 이런식으로 html 페이지가 잘 나온 것을 알 수 있다.


다음 다시 diary_project의 urls.py 에 들어가서 urlpatterns에 하나를 더 추가해주도록 하겠다.


from django.contrib import admin
from django.urls import path
import diary.views
from django.conf.urls import include # 새로 추가
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', diary.views.index, name='index'),
    path('post/', include('diary.urls')), #새로 추가
]


이렇게 되면 localhost:8000/post/로 들어오는 것들은 diary.urls에서 처리해주겠다라는 말이 된다. 이렇게 코드를 작성해주면 diary/urls가 없기 때문에 에러가 나게 될 것이다.

따라서 diary 폴더 안에 urls.py를 새로 하나 만들어 주고 아래와 같이 코드를 적어준다.


from django.urls import path
from diary import views

urlpatterns = [
    path('', views.index, name='index'), # 'localhost:8000/post/'
]


post/로 들어왔을 때도 views.index를 보여주겠다라는 것이므로 views.index함수를 두 번째 인자로 적어준다. 


다음으로는 model을 작성해주어야 한다. 

diary에 models.py 파일에 아래와 같이 코드를 작성해주자. 각각의 필드는 다른 것을 사용해도 된다. 나는 diary에 필요한 필드로 우선 제목, 내용, 그리고 만족도를 넣어주었고 title과 만족도는 굳이 길지 않아도 되니, max_length를 지정해주고 CharField 타입으로 정해주었다. 


from django.db import models
from django.utils import timezone

# Create your models here.
class Post(models.Model): 
 
    title = models.CharField(max_length=256)
    content = models.TextField()
    satisfaction= models.CharField(max_length=1)
    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(blank=True, null=True)

    def update_date(self): 
        self.updated_at = timezone.now()
        self.save()

    def __str__(self):
        return self.title


여기서 id는 자동으로 추가해주기 때문에 굳이 field로 명시해줄 필요가 없다. 

 

그리고 이렇게 모델이 바뀌었다면 우리는 꼭 migration을 시켜주어야 한다. 

python manage.py makemigrations
python manage.py migrate

위 두 줄을 각각 terminal에 입력하여 migration을 시켜주자. 

 


이제 모델이 바뀌었으니 다시 view.py와 index.html을 바꾸어주어야 한다. view.py에서는 각각의 post 객체를 모두 다 index.html로 넘겨주도록 하겠다. 

 

그래서 우선 객체를 받아서 이를 넘겨주는 식으로 아래와 같이 view.py를 수정해주었다.

from django.shortcuts import render
from .models import Post

# Create your views here.
def index(request):
    posts=Post.objects.all()
    return render(request, 'diary/index.html', {'posts': posts})


그 다음에 template에 있는 index.html도 받은 post 객체를 화면에 띄울 수 있도록 수정해준다. 

 

index.html 파일을 아래와 같이 수정해준다.

<!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>My diary</title>
  </head>
  <body>
    <h1>Diary page</h1>
    {%for post in posts%}
    <div style="border: 2px solid green;">
      <a href="/post/{{post.id}}">
        <h3> {{post.title}} </h3>
      </a>
      <h3> satisfied: {{post.satisfaction}} </h3>
      <h3> {{post.content}} </h3>
    </div>
    {% endfor %}
  </body>
</html>

 

이렇게 하면 posts라는 모든 객체 중에 for문을 돌면서 하나의 객체 post에 대해 title, satisfaction, content를 출력해준다. 


이렇게 해서 models, view, urls, templates 의 관계를 알아보았다. 이를 우리는 django에서 MTV 패턴이라고 한다. MTV 패턴은 Model, Template, View의 약자로 이 세 가지가 연계되는 패턴을 의미한다. 위의 설명을 잘 따라갔다면 이것이 무엇을 의미하는지 이해할 수 있을 것이다.

 

Model은 데이터를 저장하는 형태를 설정하고, Template 안에 있는 html 파일에서 유저에게 보여줄 화면을 설정하고, View에서 데이터를 처리하여 html 파일과 연결시켜준다. 

 

이러한 django의 MTV 패턴을 잘 익혀두면 전반적인 큰 그림을 이해하기 쉽기 때문에 오래 걸리더라도 이해해보자. 

 


 여기까지 하면 django의 MTV 패턴을 이해할 수 있지만 새로운 posting을 추가하거나, 삭제하거나, 수정할 수 없다. 다음 포스팅에서는 diary의 추가적인 기능을 구현해보도록 하겠다.


2월 06, 2024

python time.sleep() 함수, 초 단위 sleep, 밀리세컨즈

 파이썬 sleep 함수에 대해서 알아보자. 

 

sleep 함수는 파이썬에서 프로그램을 일시정시한다, 즉 재운다 (sleep)이라는 의미를 가지고 있다. 

원하는 시간  후에 프로그램을 실행시키고 싶거나 thread에서 자주 사용되는 함수이다.

 

sleep 함수는 파이썬에서 프로그램을 일시정시한다, 즉 재운다 (sleep)이라는 의미를 가지고 있다. 

원하는 시간  후에 프로그램을 실행시키고 싶거나 thread에서 자주 사용되는 함수이다.

 

먼저 sleep 함수를 사용하기 위해서는 time library를 import 해주어야 한다.

import time

이후에 sleep 함수의 () 안에 정지하고자 하는 초를 써주면 된다.

 

그리고 datetime library를 통해 sleep 함수를 더 잘 알아볼 수 있다.

 

import datetime # 날짜 시간 출력을 위한 import
import time     # sleep 함수를 위한 import

print("#####test 시작#####")
now = datetime.datetime.now()
print("*show time before sleep:", now.strftime('%H:%M:%S')) # sleep 함수 사용 전 시간 출력

#sleep 함수 적용
time.sleep(5) # 5 초 딜레이

now = datetime.datetime.now()
print("*show time after sleep:", now.strftime('%H:%M:%S')) #sleep 함수 사용 후 시간 출력

위의 예시의 코드 실행 결과는 아래와 같다.




이런식으로 출력된 것을 볼 수 있다. 정확히 우리가 sleep 시켰던 5초동안 delay가 있었던 것을 알 수 있다. 


위에서는 5초 동안의 delay를 주기 위해서 time.sleep(5) 라는 식으로 적어주었지만,

time 함수가 꼭 정수로 1초,2초,3초... 만 가능한 것은 아니다.

time.sleep() 괄호 안에 들어가는 parameter는 정확히 말해 float 형태이기 때문에 0.1, 0.01 등과 같이 소수점이 있어도 parameter에 들어갈 수 있어, 정교한 작업이 가능하다. 

 

예시로 0.125초 만큼 sleep을 시켜보도록 하겠다.

참고로 밀리세컨즈 단위를 출력하기 위해서는 추가로 .%f 를 쓰고 소수점 단위를 지정해주면 된다.

import datetime
print(now.strftime('%H:%M:%S.%f')[:-3]) # 현재 시간 소수점 아래 3자리까지 출력

위와 같이 원하는 소수점 단위를 출력해주면 되며, 이를 사용하여 0.125초만큼 sleep을 시켜주고 실제 time이 0.125초만큼 차이가 나는지 살펴보도록 하자.

 

import datetime 
import time    

print() #여백을 위해..
print("##########test 시작##########")
now = datetime.datetime.now()
print("*show time before sleep:", now.strftime('%H:%M:%S.%f')[:-3]) # sleep 함수 사용 전 시간 출력

time.sleep(0.135) # 5 초 딜레이

now = datetime.datetime.now()
print("*show time after sleep:", now.strftime('%H:%M:%S.%f')[:-3]) # sleep 함수 사용 후 시간 출력
print()

이런식으로 0.125초 동안 sleep이 잘 된 것을 알 수 있다. 


time.sleep() 함수는 간단한 것처럼 보이지만 thread 등에서도 유용하게 활용될 수 있으니 잘 알아두도록 하자.



2월 02, 2024

[Python Turtle] 현재 좌표 구하기

Python turtle로 그리다 보면, 문득 내 현재 위치는 어디일까 궁금해지는 때가 있다. 

 

도형을 그리다 보면 직선 외에도 다양한 모양으로 그림을 그리게 되는데, 현재 좌표를 알아야 그리고 싶은 그림을 더 유사하게 그릴 수 있기 때문이다. 

 

예시로, 모든 도형은 원이나 직선이 아니기에 아래 코드까지 그림을 그렸다고 가정해보자.

import turtle as t
t.shape("turtle")
t.speed(5)
t.width(5)
t.penup()
t.setposition(50,160)
t.pendown()
t.circle(-200,-15)
t.circle(-400,-5)

그러면 특히 온전한 360도 원을 그린 것이 아니기 때문에 현재 위치를 정확하게 알 수 있는 방법은 더더욱 없다. 

 

그럴 때 사용하면 좋은 것이,

 

xcor() 와 ycor() 라는 것이다. 이름이 의미하는 것처럼 xcor()는 현재 turtle의 x축 좌표 위치, ycor()는 현재 turtle의 y축 좌표 위치를 의미한다. 

해당 숫자를 return하기 때문에 우리는 terminal에서 return 된 숫자를 볼 수 있다.

 

그러기 위해서는 먼저 코드에 한 줄을 추가해준다. 

import turtle as t
t.shape("turtle")
t.speed(5)
t.width(5)
t.penup()
t.setposition(50,160)
t.pendown()
t.circle(-200,-15)
t.circle(-400,-5)
print(t.xcor(), t.ycor())

 

마지막 라인을 추가해주었다. 그 결과 터미널에서는 아래와 같은 결과값을 return한 것을 볼 수 있다. 

 

-35.04424830976332 142.6918830565497

앞의 숫자는 xcor()의 반환값, 즉 x축 좌표, 뒷 숫자는 ycor()의 반환값, 즉 y축 좌표값을 의미한다. 

 

매우 정교하게 소수점 아래로도 여러 숫자가 나오기 때문에 참고하여 더 정밀한 그림을 그릴 수 있을 듯 하다. 


8월 30, 2023

[Python] Split 함수에 대해 알아보자 (sep, maxsplit 예제)

파이썬 문자열을 특정 기준으로 나누어 리스트로 만들수 있는 함수가 있다. 

가장 대표적으로 예시를 생각해보았을 때, 만약 문자열이 띄어쓰기를 기준으로 "a b c d z k" 이런 식으로 있다면 우리는 이 문자열을 띄어쓰기를 기준으로 쪼개서 각각 list의 0번째에는 a가, list의 1번째에는 b가 2번째에는 c가... 

이렇게 들어갈 수 있도록 만들고 싶은 것이다.

 

이처럼 파이썬은 이와 같은 경우에 split 함수를 사용한다. 

 

split 함수도 간단해보이지만 parameter에 무엇이 들어가냐에 따라 조금씩 사용법이 달라지게 된다.


1. 문자열.split() => 디폴트로 띄어쓰기와 엔터에 의해 구분되는 경우 

가장 대표적으로 split 함수를 적용할 수 있는 경우이다. 

어떤 기준에 의해 split 되는지가 명시되어 있지 않은 경우에는 default로 띄어쓰기와 엔터에 의해 구분된다. 

 

즉, 위에서 예시로 들었던 것과 같이 

s= "a b c d e f g"
div= s.split()

이라고 했을 경우 div 에는 각각 a/b/c/d/e/f/g 로 쪼개진 배열이 만들어진다고 생각하면 된다.


2. 문자열.split( '구분자' ) => 원하는 구분자로 split하고 싶을 경우

 

반면 모든 문자열이 띄어쓰기로 구분이 되어있지 않을 수도 있다. 예를 들어 "a/b/c/d"라는 문자열이 있다면 우리는 "/" 에 의해 구분하고 싶을 것이다. 이처럼 띄어쓰기가 아닌 다른 구분자에 의해 문자열을 구분하고 싶다면 split 함수 괄호 안에 구분하고 싶은 구분자를 써준다. 

 

마찬가지로 아주 간단한 예시를 들어보자.

s= "a.b.c.d.e.f.g"
div= s.split('.')

1번의 경우와 거의 동일하지만 이번에는 구분자가 띄어쓰기가 아닌 '.' 인것만 다르다. 이럴 경우에 split 함수 괄호 안에 ','를 써서 구분할 수 있다.

 

명시적으로 구분자가 '.' 다 라고 말하는 방법도 있다.

 

바로 split (sep ='.')를 사용하는 것이다. 

s= "a.b.c.d.e.f.g"
div= s.split(sep= '.')

이는 위와 같은 문법이지만 조금 더 명시적으로 나는 점에 의해 구분하고 싶다라는 의미의 가독성을 높여준다.

 


3. 문자열.split(sep= '구분자', maxsplit = 숫자) => 모든 구분자로 split 하지 않고 나누는 최대 횟수를 제한하고 싶을 때 

 

문자열을 구분하고는 싶으나 나누는 최대 횟수를 제한하고 싶을 때가 있다.

예를 들어 aa.bb.cc.dd.ee라는 문자열이 있는데 aa / bb/ cc/ dd.ee 이렇게 나누고 싶을 수 있다. 즉 모든 구분자 .에 의해 split하는 것이 아니라, 나누는 최대 횟수를 제한하는 경우이다. 

 

이런 경우는 2번처럼 구분자 parameter 뒤에 maxsplit parameter를 하나 더 넣어주면 된다. 

s= "a.b.c.d.e.f.g"
div= s.split(sep= '.', maxsplit=3)

이런식으로 써 주면 div에는 a / b/ c / d.e.f.g 로 나누어진 숫자 4짜리 배열이 만들어 질 것이다.


이런식으로 오늘은 python split 함수에 대하여 알아보았다. 

간단해보이지만 다양한 문법이 숨어있고, 유용한 경우가 많으니 잘 활용하길 바란다. 

 

python은 이러한 함수 덕분에 string을 처리하기 유리한 언어라고도 알려져있다.