반응형

**리스트 컴프리헨션(List Comprehension)**은 Python의 강력한 문법 중 하나로, 짧고 간결하게 리스트를 생성할 수 있습니다. Python에서 데이터를 다루는 과정에서 리스트 컴프리헨션은 높은 가독성과 효율성을 제공하며, 간단한 데이터 변환부터 복잡한 필터링 작업까지 폭넓게 활용됩니다.

이번 글에서는 리스트 컴프리헨션의 기본 사용법부터 고급 활용법까지, 모든 것을 이해하기 쉽게 정리해 보겠습니다.

리스트 컴프리헨션이란?

리스트 컴프리헨션은 한 줄의 코드로 새로운 리스트를 생성할 수 있는 Python 문법입니다. 일반적인 for 루프와 조건문을 간략하게 표현할 수 있어 코드 작성과 가독성을 크게 향상시킵니다.

기본 문법 구조

[expression for item in iterable if condition]​
  • expression: 새로 생성될 리스트의 각 요소를 나타냅니다.
  • for item in iterable: 반복 가능한 객체(리스트, 튜플 등)를 순회합니다.
  • if condition (선택 사항): 조건이 True일 때만 해당 요소를 추가합니다.

리스트 컴프리헨션의 장점

  1. 간결한 문법
    일반적인 for 루프보다 짧고 간단하게 작성할 수 있습니다.
  2. 높은 가독성
    리스트 컴프리헨션은 의도를 명확히 표현하므로 코드의 가독성을 높입니다.
  3. 성능 최적화
    내부적으로 Python의 C 구현을 활용해 일반적인 for 루프보다 더 빠르게 작동합니다.
  4. 유연한 확장성
    조건문, 중첩 루프, 데이터 변환 등 다양한 작업을 간단히 처리할 수 있습니다.

리스트 컴프리헨션 기본 사용법

1. 단순 리스트 생성

기존 방식과 리스트 컴프리헨션을 비교해 봅시다.

기존 방식:

numbers = []
for i in range(5):
    numbers.append(i)
print(numbers)  # [0, 1, 2, 3, 4]

리스트 컴프리헨션:

numbers = [i for i in range(5)]
print(numbers)  # [0, 1, 2, 3, 4]​

2. 조건을 사용한 리스트 생성

if 조건문을 활용해 짝수만 포함된 리스트를 생성합니다.

기존 방식:

even_numbers = []
for i in range(10):
    if i % 2 == 0:
        even_numbers.append(i)
print(even_numbers)  # [0, 2, 4, 6, 8]​

리스트 컴프리헨션:

even_numbers = [i for i in range(10) if i % 2 == 0]
print(even_numbers)  # [0, 2, 4, 6, 8]​

3. 데이터 변환

리스트의 각 요소를 제곱으로 변환합니다.

squared_numbers = [i ** 2 for i in range(5)]
print(squared_numbers)  # [0, 1, 4, 9, 16]​

 


리스트 컴프리헨션 고급 활용법

1. 중첩 루프

다중 루프를 활용해 모든 조합을 생성할 수 있습니다.

pairs = [(x, y) for x in range(3) for y in range(3)]
print(pairs)  # [(0, 0), (0, 1), ..., (2, 2)]​

 


2. 조건과 중첩 루프 결합

조건문과 중첩 루프를 조합해 특정 조건에 맞는 결과를 생성합니다.

filtered_pairs = [(x, y) for x in range(5) for y in range(5) if x != y]
print(filtered_pairs)
# [(0, 1), (0, 2), ..., (4, 3)]​

 


3. 문자열 처리

리스트의 문자열을 대문자로 변환합니다.

words = ['apple', 'banana', 'cherry']
capitalized = [word.upper() for word in words]
print(capitalized)  # ['APPLE', 'BANANA', 'CHERRY']​

리스트 컴프리헨션과 다른 자료구조

리스트 컴프리헨션은 딕셔너리, 집합, 제너레이터에도 동일하게 적용할 수 있습니다.

딕셔너리 컴프리헨션

data = [1, 2, 3, 4]
squares = {x: x ** 2 for x in data}
print(squares)  # {1: 1, 2: 4, 3: 9, 4: 16}​

집합 컴프리헨션

data = [1, 2, 2, 3, 4, 4]
unique_squares = {x ** 2 for x in data}
print(unique_squares)  # {16, 1, 4, 9}​

제너레이터 컴프리헨션

data = [1, 2, 3, 4]
squares_gen = (x ** 2 for x in data)
print(list(squares_gen))  # [1, 4, 9, 16]​

장단점

장점

  1. 코드 간결성: 짧고 직관적인 코드 작성이 가능합니다.
  2. 빠른 실행 속도: 리스트 컴프리헨션은 내부적으로 최적화되어 일반 for 루프보다 빠르게 작동합니다.
  3. 가독성: 데이터 생성의 의도를 명확히 표현할 수 있습니다.

단점

  1. 복잡성 증가 가능성: 조건문과 중첩 루프가 많아지면 오히려 코드가 읽기 어려워질 수 있습니다.
  2. 디버깅 어려움: 한 줄로 작성된 리스트 컴프리헨션은 오류 발생 시 디버깅이 어렵습니다.

결론

리스트 컴프리헨션은 Python에서 가장 강력하고 효율적인 문법 중 하나로, 단순한 데이터 변환부터 복잡한 필터링과 데이터 처리까지 광범위하게 활용됩니다. 다만, 너무 복잡하게 사용하면 가독성이 떨어질 수 있으므로 상황에 맞게 적절히 사용하는 것이 중요합니다.

Python을 더 효율적으로 사용하고 싶다면 리스트 컴프리헨션을 꼭 익혀 두세요!


추가 자료

 

지금 바로 리스트 컴프리헨션을 활용해보세요! 😊

 

 

 

728x90
반응형
반응형

 

data = {'A': [1, 2], 'B': [3, 4]}  # 딕셔너리 형태의 데이터 정의
df = pd.DataFrame(data=data)       # DataFrame 생성

 

이 코드는 딕셔너리 data를 pandas.DataFrame으로 변환하여 df라는 데이터프레임을 생성하는 간단한 작업입니다.

  • data:
    • 딕셔너리의 키 'A'와 'B'는 각각 DataFrame의 열 이름으로 사용됩니다.
    • 각 키에 해당하는 리스트 [1, 2], [3, 4]는 각 열의 값으로 사용됩니다.
  • pd.DataFrame(data=data):
    • pandas는 딕셔너리 형식의 데이터를 직접 DataFrame으로 변환할 수 있습니다.

생성된 df

코드 실행 결과는 다음과 같습니다

print(df)


#출력

   A  B
0  1  3
1  2  4

설명:

  1. 열 이름:
    • A와 B는 딕셔너리의 키로, DataFrame의 열 이름으로 설정됩니다.
  2. 행 인덱스:
    • pandas는 자동으로 정수형 인덱스 [0, 1, ...]를 생성합니다.
  3. :
    • 각 키에 연결된 리스트 [1, 2]와 [3, 4]는 열 값으로 매핑됩니다.

요약

  • 이 코드는 딕셔너리를 pandas.DataFrame으로 변환하는 기본적인 작업입니다.
  • 열 이름은 딕셔너리의 키에서 가져오고, 각 키에 연결된 리스트는 열 데이터로 사용됩니다.
  • 자동으로 행 인덱스가 생성됩니다. 필요하다면 index 매개변수를 사용하여 커스텀 인덱스를 지정할 수도 있습니다.
728x90
반응형
반응형

Unit fluent-bit.service could not be found 에러는 Fluent Bit이 시스템 서비스로 설치되지 않았거나, 서비스 이름이 다를 때 발생할 수 있습니다. 이 문제를 해결하기 위해 다음 단계를 따라 문제를 해결할 수 있습니다.

1. 서비스가 올바르게 설치되었는지 확인

Fluent Bit이 제대로 설치되었는지 확인

which fluent-bit

이 명령어는 Fluent Bit의 실행 파일이 어디에 설치되어 있는지 확인합니다. 실행 파일 경로가 반환되지 않으면 Fluent Bit이 설치되지 않았거나 설치 경로가 올바르지 않을 수 있습니다.

2. 올바른 서비스 이름 찾기

Fluent Bit의 서비스 이름이 다를 수 있으므로, 다음 명령어로 서버에 어떤 서비스가 등록되어 있는지 확인 가능합니다.

systemctl list-units --type=service | grep fluent

이 명령어는 Fluent Bit과 관련된 모든 서비스를 나열합니다. 만약 fluent-bit이 아닌 다른 이름(예: td-agent-bit)으로 서비스가 등록되어 있다면, 해당 이름을 사용해 상태를 확인하고 서비스를 정지할 수 있습니다

sudo systemctl status td-agent-bit
sudo systemctl stop td-agent-bit

3. Fluent Bit을 수동으로 실행한 경우

Fluent Bit이 시스템 서비스로 설치되지 않고, 수동으로 실행된 경우에는 수동으로 프로세스를 찾아 종료해야 합니다.

  1. Fluent Bit의 프로세스를 찾습니다
ps aux | grep fluent-bit

 

   2. 실행 중인 Fluent Bit 프로세스의 PID(프로세스 ID)를 확인한 후, 다음 명령어로 종료합니다

sudo kill <PID>

4. Fluent Bit을 서비스로 설정하기

만약 Fluent Bit이 시스템 서비스로 설정되지 않은 경우, 수동으로 Fluent Bit을 서비스로 설정할 수 있습니다. 다음 단계를 통해 설정할 수 있습니다.

 

서비스 파일을 생성합니다

sudo nano /etc/systemd/system/fluent-bit.service

 

위에 생성한 파일에 아래 내용을 추가합니다.

[Unit]
Description=Fluent Bit
After=network.target

[Service]
ExecStart=/usr/local/bin/fluent-bit -c /path/to/your/fluent-bit.conf
Restart=always

[Install]
WantedBy=multi-user.target
  •  ExecStart에 설치된 Fluent Bit의 경로와 설정 파일 경로를 정확히 입력합니다.

서비스 파일을 저장하고 나옵니다. 이후 다음 명령어로 서비스를 리로드하고 시작합니다

sudo systemctl daemon-reload
sudo systemctl enable fluent-bit
sudo systemctl start fluent-bit
728x90
반응형
반응형

PostgreSQL에서 시퀀스(sequence)는 주로 자동 증가(primary key) 필드를 위한 값을 생성하는 데 사용됩니다. 시퀀스를 초기화하는 것은 데이터베이스 테이블의 ID 값 등을 재설정하거나, 특정 값부터 시작하게 하고 싶을 때 유용합니다. 이번 포스트에서는 PostgreSQL에서 시퀀스를 초기화하는 방법을 단계별로 알아보겠습니다.

1. PostgreSQL 시퀀스란?

시퀀스는 PostgreSQL에서 자동 증가 컬럼에 주로 사용되는 객체로, 테이블의 특정 컬럼이 새 레코드를 추가할 때마다 고유한 값을 자동으로 할당해줍니다. 일반적으로 시퀀스는 SERIAL이나 BIGSERIAL 타입을 통해 생성되며, 시퀀스가 생성되면 테이블이 해당 값을 참조하게 됩니다.

2. 시퀀스 초기화가 필요한 상황

시퀀스를 초기화하는 상황은 다음과 같습니다:

  • 테이블의 ID 값 등을 재설정해야 할 때
  • 데이터 삭제 후 특정 값부터 시작하도록 설정할 때
  • 잘못된 시퀀스 값을 바로잡아야 할 때

예를 들어, 데이터를 삭제한 후 시퀀스가 다음에 삽입될 레코드에서 1부터 다시 시작하도록 설정하고 싶다면 시퀀스 초기화가 필요합니다.

3. PostgreSQL에서 시퀀스 초기화하기

시퀀스를 초기화하는 방법에는 여러 가지가 있지만, 가장 일반적인 방법은 RESTART 명령어를 사용하는 것입니다. ALTER SEQUENCE 구문을 사용하여 특정 값부터 시퀀스를 다시 시작하도록 설정할 수 있습니다.

-- 기본 시퀀스 초기화 (1부터 시작)
ALTER SEQUENCE 시퀀스이름 RESTART WITH 1;

예제

user_id_seq라는 시퀀스를 1부터 다시 시작하고 싶다면 다음과 같이 설정할 수 있습니다.

ALTER SEQUENCE user_id_seq RESTART WITH 1;

위의 구문은 user_id_seq 시퀀스가 다음에 사용할 값을 1로 재설정합니다.

시퀀스를 현재 최대값으로 동기화하기

테이블의 최대 ID값과 시퀀스를 일치시키고 싶을 때는 setval 함수를 사용할 수 있습니다. 다음과 같이 setval을 사용하여 시퀀스를 초기화할 수 있습니다.

-- 특정 시퀀스를 테이블의 최대값으로 초기화하기
SELECT setval('시퀀스이름', (SELECT MAX(컬럼명) FROM 테이블이름));

 

예를 들어, user_id_seq 시퀀스를 users 테이블의 id 컬럼의 최대값으로 설정하려면 다음과 같습니다.

SELECT setval('user_id_seq', (SELECT MAX(id) FROM users));

 

4. 시퀀스 초기화 주의사항

  • 트랜잭션 관리: 시퀀스 초기화는 트랜잭션으로 처리되지 않기 때문에, 변경 후 복구가 필요할 수 있습니다.
  • 동시성: 시퀀스 초기화 작업이 다른 트랜잭션과 충돌하지 않도록 주의해야 합니다.
  • 자동 증가 컬럼 유지보수: 만약 여러 테이블에 적용되는 시퀀스가 있다면, 다른 테이블의 시퀀스도 확인이 필요합니다.

결론

PostgreSQL에서 시퀀스 초기화는 데이터베이스의 ID와 같은 고유 값을 재설정하거나 특정 값부터 시작하도록 설정할 때 유용합니다. ALTER SEQUENCE 구문과 setval 함수를 활용하여 시퀀스를 초기화하고, 시퀀스를 설정할 때 데이터의 동기화와 성능을 고려하면 더욱 효과적입니다.

728x90
반응형
반응형

데이터베이스 설계에서 테이블의 컬럼 수는 성능과 관리 효율성에 큰 영향을 미칩니다. 특히 PostgreSQL과 같은 관계형 데이터베이스에서는 컬럼 수를 적절하게 제한하는 것이 중요합니다. 오늘은 PostgreSQL에서 권장되는 컬럼 수와 성능을 고려한 데이터베이스 설계 팁을 알아보겠습니다.

1. PostgreSQL의 컬럼 수 한계

PostgreSQL은 테이블 당 최대 1,600개의 컬럼을 허용합니다. 이론적으로는 많은 수의 컬럼을 포함할 수 있지만, 실무에서 이렇게 많은 컬럼을 가진 테이블을 설계하는 것은 좋지 않습니다. 너무 많은 컬럼은 성능 저하, 데이터 관리의 어려움 등을 초래할 수 있기 때문입니다.

2. 실무에서 권장되는 적정 컬럼 수

PostgreSQL에서 50개 이하의 컬럼이 가장 이상적인 수치입니다. 이는 유지보수성, 인덱스 관리, 쿼리 성능을 종합적으로 고려한 결과입니다. 실무에서는 테이블의 컬럼 수가 많아지면 관리가 어려워지고, 불필요한 데이터 전송이 많아져 쿼리 성능이 저하될 수 있습니다.

50개 이상 200개 이하의 컬럼은 특정 요구 사항에 따라 허용될 수 있지만, 200개 이상의 컬럼을 초과할 경우 성능 저하가 본격적으로 나타나므로 가능한 피하는 것이 좋습니다. 예를 들어, 너무 많은 컬럼이 포함된 테이블에서 SELECT * 쿼리를 실행하면 불필요한 데이터를 전송하게 되어 응답 속도가 느려질 수 있습니다.

3. 성능 최적화 및 설계 팁

테이블의 컬럼 수를 적정 수준으로 유지하면서 성능을 극대화하는 몇 가지 팁을 소개합니다.

  • 정규화: 데이터 중복을 줄이고 필수적인 정보만 남겨두는 정규화를 통해 불필요한 컬럼을 줄일 수 있습니다. 이렇게 하면 테이블이 더 간결해지고 관리가 쉬워집니다.
  • 데이터 타입 최적화: 컬럼의 데이터 타입을 최소한의 크기로 지정하여 데이터 저장 공간을 효율적으로 관리하세요. 예를 들어, 정수형 데이터에는 INT 대신 SMALLINT와 같은 작은 크기의 데이터 타입을 사용할 수 있습니다.
  • 인덱스 관리: 컬럼이 많을수록 인덱스 관리가 복잡해집니다. 필수적인 컬럼에만 인덱스를 추가하고, 자주 사용하지 않는 컬럼에는 인덱스를 추가하지 않는 것이 좋습니다.
  • 컬럼 그룹화: 비슷한 역할을 하는 컬럼들을 하나의 테이블에 모두 포함시키는 대신, 1:1 관계의 별도 테이블로 분리하는 방법을 고려할 수 있습니다. 예를 들어, 고객 정보를 저장하는 테이블에서 연락처 관련 컬럼을 별도의 테이블로 분리하면 쿼리 성능과 관리 효율이 개선될 수 있습니다.
  • JSONB 사용: 만약 컬럼이 1,600개에 가까워야 한다면, JSONB 데이터 타입을 활용해 비정형 데이터를 JSON 형태로 저장하는 것도 하나의 방법입니다. 이렇게 하면 유연한 구조로 다양한 데이터를 담을 수 있습니다.

4. 주의할 사항

테이블을 너무 많이 분리하면 JOIN 연산이 많이 발생하여 쿼리 성능이 저하될 수 있습니다. 데이터베이스 설계 초기 단계에서부터 컬럼 수를 최적화하는 것이 필요하며, 미래 확장성도 고려하여 테이블 설계를 진행해야 합니다.

결론

PostgreSQL에서 적절한 컬럼 수는 약 50~100개 수준입니다. 가능하다면 200개 이상의 컬럼을 포함하는 것을 피하는 것이 성능과 관리 측면에서 좋습니다. 데이터베이스 설계는 현재뿐만 아니라 향후 데이터 확장성과 성능을 고려한 장기적인 관점에서 접근해야 합니다.

728x90
반응형
반응형

아래와 같이 해당 BOOLEAN 타입의 컬럼 값을 반전시켜 저장하려고 하는 쿼리가 있습니다.

update table 
set column = !column 
where seq = 1

 

실행을 하면 오류가 발생하는데요 이유는 PostgreSQL에서 ! 연산자는 지원되지 않기때문입니다.

대신 NOT 키워드를 사용해야 합니다.

해결 방법

컬럼의 값을 반전시키기 위해 아래와 같이 쿼리를 수정합니다.

UPDATE table
SET column = NOT column
WHERE seq = 1;

 

설명

  • NOT column은  컬럼의 값을 True에서 False로, 또는 False에서 True로 반전시킵니다.
  • 컬럼이 BOOLEAN 타입일 때만 NOT 연산을 사용할 수 있습니다.
728x90
반응형
반응형

혼공 머신러닝 예제 진행 중 발생한 문제로

혼공 머신러닝의 경우 코렙사용을 기준으로 예제가 작성되다 보니 종종 직접 설치해야 하는 라이브러리들이 생깁니다.

!wget https://bit.ly/fruits_300_data -O fruits_300.npy

위의 코드도 그런 문제인데 실행해보면 ModuleNotFoundError: No module named ‘wget’ 이란 오류 메세지가 나오게 됩니다.

모듈을 못찾으니 conda list 또는 pip list로 설치된 모듈들을 확인 실제 존재 하지 않는다면( 당연히 없을 확률이 훨씬 높습니다)

conda install wget
or
pip intsll wget

설치를 하고 모듈을 설치 했으니 당연히 import wget 해서 모듈 import를 진행했는데 ModuleNotFoundError: No module named ‘wget’ 오류가 다시 나오게 됩니다.

wget은 리눅스 커널 명령어여서 그런지 import필요없이 처음 실행하고자 하는 코드를 그대로 실행하면 문제없이 파일 다운로드가 진행 됩니다.

구글링을 통해 다른 분들의 사례를 보면 설치 import를 해야 한다고 하는데 저는 오히려 import없이 진행해야 오류가 없던데 이유를 찾지는 못했네요.

참고로 wget 앞에 느낌표(!)는 리눅스 셸 명령임을 코드셸에 알려주기 위해 사용합니다.

728x90
반응형
반응형
let { type } = req.params;

위의 코드는 구조 분해 할당 (Destructuring Assignment)을 사용한 것입니다. . 아래는 이에 대한 상세 설명입니다.

 

1. req.params:

  • 이 코드는 Express.js 애플리케이션에서 사용됩니다. 여기서 req는 **요청 객체(request object)**입니다.
  • req.params는 URL에서 **경로 매개변수(route parameters)**를 담고 있는 객체입니다. 이 매개변수들은 일반적으로 경로에서 : 기호로 정의됩니다. 예를 들어:
app.get('/user/:type', (req, res) => {
  // req.params.type은 ':type'의 값을 가집니다
});
  • 경로가 /user/:type일 경우, type은 경로 매개변수가 되며, req.params는 다음과 같은 객체가 됩니다
{ type: 'someValue' }

 

2. 구조 분해 할당 (Destructuring Assignment):

  • { type } 구문은 구조 분해 할당입니다. 이는 객체에서 속성을 추출하는 간편한 방법입니다.
  • 원래는 다음과 같이 작성될 수 있습니다:
let type = req.params.type;

이를 아래와 같이 간략하게 작성할 수 있습니다:

let { type } = req.params;
 
  • 이 코드는 req.params 객체에서 type 속성을 추출하여 새로운 변수 type에 할당합니다.

요약

let { type } = req.params;는 req.params 객체에서 type이라는 매개변수를 추출하여 type이라는 변수에 저장하는 코드입니다. 이는 주로 Express.js에서 URL 경로의 매개변수를 쉽게 접근하기 위해 사용됩니다.

728x90
반응형

+ Recent posts