반응형

https://www.acmicpc.net/problem/2563

 

요약하자면, 2차원 행렬의 공간의 모든 값을 더하는 문제이다.

 

정답 코드

import sys

l = [[0 for _ in range(100)] for _ in range(100)]

next(sys.stdin)
for line in sys.stdin:
    x, y = map(int, line.split())
    for j in range(x, x + 10):
        for i in range(y, y + 10):
            l[i][j] = 1

sys.stdout.write(f"{(sum(sum(l, [])))}")

 

2차원 행렬에 값을 입력받는 것은 수월하게 할 수 있다.

2차원 행렬을 row, column 양방향으로 iterate를 돌면서 합하면 간단하지만, 대신에 2차원 list를 1차원 리스트로 변환해서 한번에 더하는 코드를 사용했다.

sum(sum(2차원 list, []))

sum의 두번째 인자에 []를 주면, 2차원 list의 각 item인 1차원 list를 이 []에 하나씩 뒤에 더하게 된다.

반응형
반응형

Path Parameter(경로 매개변수)Query Parameter(쿼리 매개변수)는 web API나 URL에서 데이터를 전달하기 위한 방법으로, 각각의 용도와 목적이 다르다.

둘다 주로 GET 요청에서 많이 사용된다. GET 요청의 주요 목적이 서버에서 데이터를 읽어오고 리소스를 검색하는 것이기 때문인데, GET 요청은 요청 데이터를 URL에 포함하여 전달하므로 Path Parameter와 Query Parameter를 사용하는 것이 자연스럽다. 주의할 점은, GET 요청은 URL에 모든 데이터가 노출되기 때문에 민감한 데이터를 전달하는 데 적합하지 않다(이런 경우 POST 요청이나 본문(body)을 사용하는 것이 권장된다).

 

1. Path Parameter(경로 매개변수)

  • 위치: URL의 특정 경로 부분에 포함된다.
    예: https://example.com/users/{user_id}/orders/{order_id}
  • 용도:
    • Resource 식별: 특정 resource를 명확히 식별하기 위해 사용된다.
    • API 구조를 계층적으로 만들고 의미를 전달하는 데 적합하다.
  • 특징:
    • 필수적으로 사용되는 경우가 많다.
    • 일반적으로 고정된 값으로 나타나며 RESTful 설계에서 흔히 사용된다.
  • 예제:
    • 12345products라는 resource의 특정 제품 ID를 나타낸다.

 

2. Query Parameter(쿼리 매개변수)

  • 위치: URL의 끝에 ? 뒤에 key-value 쌍 형태로 나타난다. 여러 query parameter는 &로 구분된다.
    예: https://example.com/search?query=shoes&sort=price_asc
  • 용도:
    • Resource를 filtering하거나 sorting, paging, 또는 검색 조건을 전달할 때 사용한다.
    • 선택적 데이터를 추가하기에 적합하다.
  • 특징:
    • 선택적으로 사용할 수 있다.
    • 가변적인 데이터를 표현하기에 적합하다.
  • 예제:
    • category=electronics는 전자제품 카테고리를 필터링하고, limit=10은 한 페이지당 10개, page=2는 두 번째 페이지를 요청한다.

 

차이점 요약

항목 Path Parameter (경로 매개변수) Query Parameter (쿼리 매개변수)
위치 URL 경로의 일부 URL 끝의 ? 뒤
용도 Resource 식별 Filtering, Sorting, 검색 조건 전달
필수 여부 일반적으로 필수 선택적
가독성 명확하고 계층적 구조 표현에 적합 복잡한 조건 표현에 유용

 

결합 사용 예제

Path Paramter와 Query Paramter를 함께 사용할 수도 있다.

  • Path Paramter : 12345는 특정 사용자를 식별.
  • Query Paramter : status=pending은 대기 중인 주문만, limit=5는 결과를 5개로 제한.
반응형
반응형

Pydantic이란?

Pydantic은 Python의 데이터 검증 라이브러리이다. 주로 데이터 모델을 정의하고 검증하는 데 사용되며, 특히 FastAPI와 같은 최신 웹 프레임워크에서 많이 활용된다.

 

핵심 feature와 사용법

아래 예제를 통해 Pydantic의 동작 원리를 간단히 살펴보자.

from pydantic import BaseModel
from typing import List, Optional

class User(BaseModel):
    id: int
    name: str
    email: str
    age: Optional[int] = None
    tags: List[str] = []

1. Data Validation (데이터 검증)

데이터가 정의된 타입과 일치하는지 자동으로 확인한다.

# 자동적으로 data type을 validate한다
# Type이 매치되지 않으면 ValidationError를 raise한다

# 유효한 데이터
user1 = User(
    id=1,
    name="김철수",
    email="user@example.com",
    age=25,
    tags=["developer", "python"]
)

# 잘못된 데이터 타입을 넣으면 에러 발생
try:
    user2 = User(
        id="invalid",  # int가 아닌 str
        name=123,      # str이 아닌 int
        email="invalid-email"
    )
except ValueError as e:
    print(f"검증 에러: {e}")
검증 에러: 2 validation errors for User
id
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='invalid', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
name
  Input should be a valid string [type=string_type, input_value=123, input_type=int]
    For further information visit https://errors.pydantic.dev/2.10/v/string_type

2. Type Conversion (Type 변환)

가능한 경우 데이터를 적절한 타입으로 자동 변환한다.

# 자동적으로 호환되는 type으로 형변환한다
# str "123"을 자동으로 int 123으로 변환
user = User(id="123", name="홍길동", email="hong@example.com")

3. JSON Serialization/Deserialization (JSON 직렬화/역직렬화)

# dict로 변환
user_dict = user1.model_dump()
# JSON으로 변환
user_json = user1.json()

4. Complex Data Validation (복잡한 데이터 검증)

class Order(BaseModel):
   user: User
   items: List[str]
   total: float

order = Order(
   user=user1,
   items=["item1", "item2"],
   total=29.99
)

5. 유효성 검사 규칙 추가

from pydantic import BaseModel, EmailStr, conint

class AdvancedUser(BaseModel):
    name: str
    email: EmailStr  # 이메일 형식 검증
    age: conint(ge=0, le=150)  # 0-150 사이의 정수만 허용

 

Pydantic의 Usage

  • API request/response 데이터 검증
  • 설정 파일 파싱
  • 복잡한 데이터 구조 검증
  • ORM 모델과의 통합
반응형
반응형

Django의 urlpatterns는 URL을 처리하기 위한 매핑 테이블 역할을 한다.

Django의 URL 처리 시스템은 user가 보낸 HTTP 요청의 URL을 분석하고, 해당 요청을 적절한 view 함수 또는 view 클래스로 routing하는 데 기반을 두고 있다.

 

urlpatterns의 단계별 작동 원리

1. URL 요청 수신

  • Django 프로젝트가 client의 HTTP 요청을 수신한다. 
  • 이 요청은 Django의 URLconf 시스템으로 전달된다.
    • URLconf 시스템이란, Django 프로젝트에서 URL과 뷰(view)를 매핑하기 위한 설정 체계이다.

 

2. URLconf와 urlpatterns

  • Django 설정 파일(settings.py)의 ROOT_URLCONF 변수에 명시된 모듈이 메인 URLconf로 사용된다.
# project/settings.py
ROOT_URLCONF = 'project.urls'
  • 해당 모듈에는 urlpatterns라는 이름의 list가 정의되어 있고, 이 list에는 URL 패턴과 뷰가 매핑되어 있다.

 

3. URL 매칭 과정

  • Django는 urlpatterns의 각 항목을 순서대로 비교하여 요청된 URL과 일치하는 항목을 찾는다.
  • URL 패턴을 정의하는 데 path()re_path() 함수가 사용된다.
from django.urls import path

urlpatterns = [
    path('home/', views.home, name='home'),  # 'home/' 요청 -> views.home 함수로 처리
    path('about/', views.about, name='about'),
]

 

4. URL 패턴의 동작 방식

  • path() 함수는 정규화된 URL 경로를 기반으로 URL을 매칭한다.
path('articles/<int:year>/', views.year_archive)

위 예시는 /articles/2024/ 같은 요청을 처리한다. 이때 year 변수에는 2024 값이 전달된다.

  • re_path() 함수는 정규표현식을 사용하여 URL을 매칭한다.
from django.urls import re_path

urlpatterns = [
    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
]

 

5. 뷰 함수로의 라우팅

  • 매칭된 URL 패턴에 연결된 뷰 함수나 뷰 클래스가 호출된다.
  • URL 패턴에서 캡처된 값은 뷰 함수의 argument로 전달된다.

 

6. App 사용시 URLconf 분리

  • (여러 app으로 구성된) 복잡한 프로젝트에서는 include()를 사용하여 URLconf를 분리할 수 있다.
from django.urls import include

urlpatterns = [
    path('blog/', include('blog.urls')),  # blog app의 URLconf로 위임
]
  • Namespace를 사용하면 여러 앱 간 URL 이름 충돌을 방지할 수 있다.

 

7. URL 패턴이 매칭되는 경우가 없는 경우의 처리

  • urlpatterns의 항목 중 요청된 URL과 일치하는 것이 없으면, Django는 404 Not Found 에러를 반환한다.

 

 

전체 흐름 예시

# project/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('myapp/', include('myapp.urls')),  # myapp의 URLconf로 위임
]

# myapp/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),  # 루트 URL 처리
    path('hello/<str:name>/', views.hello, name='hello'),
]
반응형
반응형

reverse() 함수는 Django에서 URL 패턴의 이름(name)을 사용해서 해당되는는 URL을 생성하는 기능을 수행한다.

이를 사용하면 URL 하드코딩을 피하고 유연한 URL 관리가 가능해진다.

 

# urls.py
path('posts/<int:post_id>/', views.post_detail, name='post_detail')

# views.py나 다른 Python 코드에서
from django.urls import reverse
url = reverse('post_detail', args=[42])  # '/posts/42/' 반환

위 코드를 보면서 reverse()의 주요 특징과 장점을 살펴보자.

  1. URL 패턴 변경에 유연하게 대응할 수 있다.
    • URL 구조가 바뀌더라도, 이름(name)이 같다면 코드를 수정할 필요가 없다.
      • (ex: "posts/42/"가 "articles/42/"로 바뀌어도 reverse() 호출은 동일하다.)
  2. 다양한 컨텍스트에서 사용 가능하다.
    • view 함수에서 redirect할 때
    • template에서 link를 생성할 때(template에서는 url 태그로 사용)
    • Model의 get_absolute_url() 메서드에서
  3. 인자 전달 방식
    • args: positional argument로 전달(list 형태)
    • kwargs: keyword argument로 전달(dict 형태)

예를 들어, template에서는 아래와 같이 사용된다:

<a href="{% url 'post_detail' post.id %}">포스트 보기</a>

 

이렇게 reverse()를 사용해서 URL을 관리하면 코드의 유지보수성이 좋아진다. URL 구조를 변경해도 이름(name) 기반으로 참조하기 때문에 개별 URL을 일일이 수정할 필요가 없어진다.

 

"reverse"라고 불리는 이유?

URL 패턴을 "거꾸로(역방향으로)" 해석하기 때문이다.

일반적인 URL 라우팅 과정:

URL 패턴 → URL → View
예: 'posts/<int:id>/''/posts/42/' → post_detail view

reverse() 함수의 동작 과정:

View 이름 → URL
예: 'post_detail''/posts/42/'

즉, 일반적인 URL 해석은 사용자가 브라우저에 입력한 URL을 받아서 해당하는 view를 찾는 과정이나, reverse()는 반대로 view의 이름을 가지고 URL을 찾아내는 과정이다. 이런 역방향 URL 해석 과정 때문에 "reverse"라는 이름이 붙은 것이다.

반응형
반응형

파이썬에서 언패킹(unpacking)은 하나의 데이터 구조(예: list, tuple, dict 등)에 포함된 여러 값을 한 번에 변수에 할당하거나, 함수 호출에서 사용하기 위해 분리하는 기능이다. 이를 통해 코드가 간결해지고 가독성이 높아진다.

다양한 사례를 통해 언패킹으로 어떤 코드 작성이 가능한지 살펴본다.

 

1. Sequence 언패킹

Sequence(예: list, tuple 등)의 값을 변수에 한 번에 할당할 수 있다.

# tuple 언패킹
a, b, c = (1, 2, 3)
print(a, b, c)  # 출력: 1 2 3

# list 언패킹
x, y, z = [4, 5, 6]
print(x, y, z)  # 출력: 4 5 6

# string 언패킹
p, q, r = "ABC"
print(p, q, r)  # 출력: A B C

*와 함께 사용한 언패킹

a, *b, c = [1, 2, 3, 4, 5]
print(a)  # 출력: 1
print(b)  # 출력: [2, 3, 4]
print(c)  # 출력: 5

 

2. 딕셔너리 언패킹

dict의 key-value 쌍을 언패킹할 때 **를 사용한다.

my_dict = {'y': 20, 'x': 10}
def my_func(x, y):
    print(x)
    print(y)

my_func(**my_dict)
10
20

my_dict가 언패킹되면서, 함수에 argument로 y=20, x=10 형태로 전달된다.

 

3. 함수 호출에서의 언패킹

함수에 여러 개의 argument를 전달할 때 *와 **를 사용하여 list, tuple, dict를 언패킹할 수 있다.

# list 및 tuple 언패킹
def add(a, b, c):
    return a + b + c

values = [1, 2, 3]
print(add(*values))  # 출력: 6

# dict 언패킹
kwargs = {'a': 1, 'b': 2, 'c': 3}
print(add(**kwargs))  # 출력: 6

 

4. 패킹과 언패킹의 조합

함수 정의에서 *args**kwargs를 사용하면 가변 길이의 argument를 받아올 수 있다. 이를 활용하면 언패킹과 조합이 가능하다.

def func(*args, **kwargs):
    print("args:", args)
    print("kwargs:", kwargs)

func(1, 2, 3, x=10, y=20)
args: (1, 2, 3)
kwargs: {'x': 10, 'y': 20}

 

5. 응용 예시

list 합치기

list1 = [1, 2, 3]
list2 = [4, 5, 6]
merged = [*list1, *list2]
print(merged)  # 출력: [1, 2, 3, 4, 5, 6]

dict 합치기

dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
merged_dict = {**dict1, **dict2}
print(merged_dict)  # 출력: {'a': 1, 'b': 2, 'c': 3, 'd': 4}

 

반응형
반응형

파이썬에서 iterable(참고)은 반복 가능한 모든 객체를 의미하며, 한 번에 하나씩 요소를 리턴할 수 있는 객체이다.

반면 sequence 자료형(짧게는 sequence)는 iterable의 하위 개념으로, 정수 인덱스로 개별 요소에 접근할 수 있는, 순서가 있는 자료형이다.

 

주요 차이점

1. 접근 방식

Sequence 자료형: indexing과 slicing이 가능하다.

my_list = [1, 2, 3]
print(my_list[0])  # 1
print(my_list[1:3])  # [2, 3]

Iterable: 반드시 indexing이 가능하지는 않다. 이런 경우 slicing도 불가능하다.

my_set = {1, 2, 3}
print(my_set[0])
TypeError: 'set' object is not subscriptable

 

2. 순서 보장 여부

Sequence 자료형: 요소의 순서가 항상 보장된다.

Iterable: 순서를 보장하지 않을 수도 있다 (ex: set, frozenset, 파이썬 3.6 이전 dict, generator(generator 구현은 순서 보장을 강제하지 않음))

 

3. 사례

Sequence 자료형: list,tuple, str, range 등

Iterable: sequence 자료형, set, dict, generator 등

 

결론

모든 sequence 자료형은 iterable이지만, 모든 iterable이 sequence 자료형은 아니다.

특성 Iterable Sequence
순서 보장 여부 순서를 보장하지 않을 수 있음 순서를 항상 보장함
Indexing 가능 여부 지원하지 않을 수 있음 (set 등) index를 통해 요소에 접근 가능
Slicing 지원 지원하지 않을 수 있음 slicing 지원
예시 set, dict, list, generator 등 list, tuple, str, range 등
반응형
반응형

Browser Object Model(BOM)이란?

웹 개발에서 DOM이란, 웹 문서를 위한 programming interface이다. HTML 문서를 객체의 tree 형태로 구조화해서, 개발자들이 웹 페이지의 콘텐츠와 구조와 스타일을 동적으로 접근, 수정 및 제어할 수 있게 해준다. DOM Tree의 각 node는 웹 문서의 구조, 스타일, 콘텐츠를 나타낸다.

 

DOM의 key features

1. Tree 구조

DOM은 웹 문서를 tree 형태로 표현한다. 이 구조는 문서 내 요소들 간의 관계를 시각적으로 이해하고 프로그래밍적으로 접근할 수 있도록 돕는다.

DOM Tree의 각 node는 다음과 같은 유형이 있다:

  • 요소(element) 노드: HTML 요소를 의미한다. ex) <html>, <div>, <p>
  • 속성(attribute) 노드: 요소의 속성을 의미한다. ex) class="classname"
  • 텍스트(text) 노드: 요소 안의 텍스트를 의미한다.
  • 문서(document) 노드: DOM tree의 최상위(Root) node로, 문서 자체를 나타낸다. document 객체를 통해 접근할 수 있다.
    • <html> 요소는 document 노드의 자식 node이며, 웹페이지의 최상위 HTML 요소를 나타낸다. <html> 요소는 HTML 문서의 최상위 요소(element)이기 때문에 "document element"이며 document.documentElement 를 통해 접근할 수 있다.
    • <head> 요소<body> 요소<html> 요소의 자식 node이며, 각각 웹문서의 메타정보와 콘텐츠를 포함한다. document.headdocument.body를 통해 접근할 수 있다.

 

<!DOCTYPE html>
<html>
  <head>
    <title>Example</title>
  </head>
  <body>
    <p>Hello, World!</p>
  </body>
</html>

위를 DOM tree로 표현하면 아래와 같다.

Document
  └── html
       ├── head
       │    └── title
       │         └── "Example" (Text node)
       └── body
            └── p
                 └── "Hello, World!" (Text node)

 

 

DOM Tree에서 각 노드는 상위(부모) node와 하위(자식) node의 관계를 가진다.

같은 부모를 공유하는 노드는 형제(sibling) 관계를 가진다.

DOM 트리의 최상위(root) 노드는 document node이다. 일반적으로 HTML 문서에서는 <html> 요소가 최상위 node의 첫 번째 자식이다. (<!DOCTYPE html>은 document node의 자식이지만, 첫 번짜 자식 node는 아니다. 브라우저는 <!DOCTYPE html> 을 독립적인 Doctype node로 유지하고, <html>을 document node의 첫 번째 요소(element) node로 처리한다)

<html>
  <body>
    <h1>Hello, World!</h1>
    <p>This is a paragraph.</p>
  </body>
</html>
  • 위 HTML 코드에 의해 <html>을 document node의 첫번째 자식으로 가진 DOM tree가 생성된다.
  • <body> node는 <html> node의 child node이다.
  • <h1> node와 <p> node는 <body> node의 child node이다.
  • <h1> node와 <p> node는 sibling(형제) 관계이다.

 

console.log(document.firstChild);
// <!DOCTYPE html> (Doctype 노드)

console.log(document.documentElement);
// <html>...</html> (언제나 <html> 요소를 가리킨다)

console.log(document.firstElementChild);
// <html>...</html> (첫 요소 노드를 말한다. <html> 이전에 주석과 같은 노드들이 있으면 값이 달라지고,
// 그게 아니면 보통은 <html> 요소를 의미한다.)

 

 

2. 동적 상호작용

개발자는 JavaScript를 사용해 DOM을 동적으로 수정할 수 있다. 요소(element)와 스타일(style)을 추가, 삭제 또는 수정할 수 있다.

const newElement = document.createElement("div");
newElement.textContent = "안녕하세요!";
document.body.appendChild(newElement);

DOM을 통해 웹 페이지의 요소들에 대한 동적이고 실시간적인 제어가 가능하다. DOM은 브라우저가 페이지를 로드한 후에도 브라우저가 즉시 반응할 수 있게 하여, 개발자가 페이지의 상태를 효율적으로 제어하고 사용자 인터페이스를 실시간으로 업데이트할 수 있게 한다.

 

 

3. 이벤트 처리(Event Handling)

웹 페이지에서 사용자와의 상호작용을 다루는 기능이다.

이벤트는 사용자 또는 시스템에서 발생하는 특정 행동을 나타낸다. 예를 들어, 버튼 클릭, 마우스 오버, 키보드 입력, 페이지 로드 등이 이벤트에 해당한다. 각 이벤트는 특정 DOM 요소에서 발생하며, 이때 이벤트가 발생한 요소에 대한 정보가 전달된다.

DOM은 이벤트를 처리하기 위해 이벤트 리스너(Event Listener)를 사용한다. 이벤트 리스너는 특정 이벤트가 발생했을 때 실행될 함수를 지정하는 역할을 한다.

이를 통해 웹 페이지에 interactive한 기능을 추가할 수 있다.

document.querySelector("button").addEventListener("click", () => {
  alert("버튼 클릭!");
});

 

이벤트는 DOM 트리에서 상위 요소로 전파될 수 있다. 이를 이벤트 캡처링과 이벤트 버블링으로 구분할 수 있다.

  • 이벤트 캡처링(Event Capturing): 이벤트가 상위 요소에서 시작해 하위 요소로 전파된다.
  • 이벤트 버블링(Event Bubbling): 이벤트가 가장 하위 요소에서 시작해 상위 요소로 전파된다. 기본적으로 이 방식이 사용된다.

상위 요소에 이벤트 리스너를 설정하여 하위 요소에서 발생한 이벤트를 처리하는 방법으로 이벤트 위임(Event Delegation)이 있다. 이를 통해 여러 개의 하위 요소에 각각 이벤트 리스너를 설정하는 대신 상위 요소에서 한 번만 이벤트 리스너를 설정하면 된다.

 

4. 플랫폼 독립적(Platform-Independent)

DOM은 브라우저나 플랫폼에 관계없이 표준화된 방식으로 스크립트가 문서와 상호작용할 수 있게 해준다.

DOM은 W3C(World Wide Web Consortium)과 같은 표준화 기관에서 정의한 규격에 따라 설계되므로, 모든 브라우저에서 동일한 방식으로 작동하며, 특정 브라우저나 운영 체제에 종속되지 않는다.

DOM은 JavaScript와 긴밀히 통합되어 있으며, JavaScript는 어떤 플랫폼에서 실행되더라도 DOM과 상호작용할 수 있다.

예를 들어, 다음 코드는 브라우저 또는 운영 체제에 상관없이 동일하게 작동한다.

document.getElementById("myElement").textContent = "Hello World!";

따라서 클라이언트와 서버 간의 플랫폼 차이를 넘어 웹 애플리케이션의 일관된 동작이 보장된다.

단, DOM 자체는 표준화되어 있지만, 일부 브라우저는 DOM API를 구현하는 방식에서 약간의 차이를 보일 수 있다. 예를 들어, 특정 API가 Internet Explorer와 같이 오래된 브라우저에서는 지원되지 않을 수 있다.

반응형
반응형

https://www.acmicpc.net/problem/1157

 

입력받은 단어 중 가장 갯수가 많은 알파벳이 무엇인지 출력하는 프로그램을 구현해야 한다(여러 개인 경우 "?"를 출력해야 한다).

 

문자열의 count() 함수 같은 것을 써서 복잡하게 풀 수도 있겠지만, collections 모듈의 Counter를 풀면 쉽게 풀 수 있겠다 생각이 들었다.

그리고 파이썬 3.10 버전부터 도입된, 아직 다소 생소한 match 문법도 써보기로 했다.

덕분에 아래와 같은 간단한 코드로 해결할 수 있었다.

 

정답 코드

from collections import Counter

word = input().upper()
c = Counter(word)
most_common_2 = c.most_common(2)

match len(most_common_2):
    case 1:
        print(most_common_2[0][0])
    case 2:
        print(most_common_2[0][0] if most_common_2[0][1] > most_common_2[1][1] else "?")

 

Counter 객체의 most_common(2) 호출은 가장 흔하게 나타난 문자 2개와 그 갯수를 tuple의 list 형태로 리턴한다.

list 요소의 갯수에 따라 분기를 다르게 탄다(여기서 match 문법 사용):

  1. list의 요소 갯수가 1개면, 가장 흔한 문자가 단독으로 1개 존재한다는 뜻이므로 그냥 그 문자를 바로 출력하면 된다.
  2. list의 요소 갯수가 2개면, 가장 흔하게 나타난 2개 문자의 실제 갯수를 따져봐야 한다.
    • (첫번째 문자의 갯수 > 두번째 문자의 갯수) 이면 그 문자를 출력한다
    • (첫번째 문자의 갯수 = 두번째 문자의 갯수) 이면 "?"를 출력한다.
    • (첫번째 문자의 갯수 < 두번째 문자의 갯수) 인 경우는 most_common()의 리턴값에서 애초에 있을 수 없다.
반응형
반응형

Git에서 local의 가장 최근 commit의 timestamp 값을 지금(now)으로 변경하는 방법이다.

$ git commit --amend --date=now --no-edit

 

  • git commit --amend: 가장 최근 commit을 수정한다는 의미이다. 신규 commit 생성이 아니다.
  • --date=now: 현재 시간으로 commit의 timestamp를 업데이트한다는 뜻이다. 이는 Commit의 Author date와 Committer date를 모두 현재 시간으로 수정한다.
  • --no-edit: 기존 commit message를 수정하지 않는다는 뜻으로, 재편집하지 않아도 되게 한다.

 

아래처럼 다른 시간으로 변경하는 방법들도 있다.

# 마지막 커밋의 날짜를 24시간 전으로 변경
git commit --amend --date="24 hours ago" --no-edit

# 또는 특정 날짜/시간으로 직접 지정할 수도 있다
git commit --amend --date="2024-02-02 15:30:00" --no-edit

 

주의할 점

commit을 amending한다는 것은 commit의 hash 값을 변경하는 것을 의미한다. 그러므로 여러 사람에게 공유된 repository에 해당 commit이 이미 push된 경우에는, 위 방법을 사용하는 것에 조심해야 한다. 

 

반응형

+ Recent posts