반응형

 

오늘은 운영 수준에서 따르면 좋은 파이썬 코딩 규칙들 3가지 정도만 소개해드리겠습니다. 출처는 블로그나 책에서 참고했습니다.

 

 

 

(1) 클래스의 내부 메소드는 _(언더바) 로 시작하는 함수명을 짓는다.

 

(2) 주석 코멘트를 잘 작성해준다.

 

(3) iteration 같은 반복자 루프에서는 null 값을 고려한 방어 코드를 작성한다.

 

 

그럼 짧게 코드로 작성해보면 아래와 같습니다.

class MyClass:

    def run(self, my_list: list[str]):

        for something in my_list or []:              (3) iterating 같은 반복자 루프에서는 null 값을 고려한 방어 코드를 작성한다.  

            self._do_something(something)

        

    

    def _do_something(self,something):   (1) 클래스의 내부 메소드는 _(언더바) 로 시작하는 함수명을 짓는다.

        print(something)

    

    def _clean() -> None:     (2) 주석 코멘트를 잘 작성해준다.



       """write clean code .. """



obj = MyClass()

obj.run(["game","movie","runing"])

 

 

 

 

 

감사합니다. 

 

 

 

.

 

 

 
반응형
반응형

 

요즘 너무 유튜브 쇼츠에 빠져있는 것 같아, "인간 실격"이라는 책을 읽었다.  출퇴근 시간에 틈틈히 읽었고, 완독 까지 두 달 정도 걸렸다.

 

책의 구조가 독특하다. 서문, 1~3번 째 수기, 후기 이렇게 목차가 구성되있는데 요조라는 남자가 본인의 일생을 일기처럼 기록한 것이 수기 부분이고, 서문과 후기는 요조의 이야기를 전하는 작가의 시점으로 되있다. 후기에서 작가는 요조의 사진과 노트를 받는 내용이 나온다.

결국 이 책은 주인공 요조라는 불행해 보일 수 있는 남자의 인생을 조망한다. 

 

“혼자만 아주 별난 사람인 듯 느껴져 불안과 공포에 바들바들 떨 뿐입니다. 저는 주위사람과 대화를 거의 나누지 못합니다. 그래서 생각해낸 묘안이 광대였습니다.”

 

유복하게 태어났고, 자기가 다른 사람과는 다름을 깨달은 요조가 남들과 섞이기 위해 어쩔 수 없이 광대 노릇을 하는 것이, 회사에서 일도 잘하고 전문적가이기 위해 애써 노력하는 나와 닮았다. 

 

 

“세상이란 개인이 아닐까 하는 흡사 사상같은 것을 터득하게 되었습니다.’”

 

세상은 다수의 인간일까? 세상의 실체가 있는걸까? 사실 세상은 너일 수 있고 , 나일 수 있다. 

 

 

 

그리고 요조는 아버지의 기대에 만족하기 위해 살아가는 것이 싫었어도, 결국 아버지의 경제적 도움 없이는 아무것도 할 수 없다는 것을 안다.  자기모순이다. 

 

 

“남부끄러운 적이 많은 일생이었습니다.”
“알코올 중독일지도 모르겠습니다. 지금도 마시고 싶거든요”
“죽고 싶다. 차라리 죽고싶다. 이제는 돌이킬 수 없다. 거듭 부끄러움을 당할 뿐이다.” 

 

 

 책을 읽는 내내 마음속으로 “술좀 그만 마셔!!”를 속으로 외치던 난 그렇게 폐인이 되어가면서 ‘인간, 실격’의 모습으로 변해가는 요조를 보고 안타까운 한숨을 내쉬고 멈췄다. 나도 그랬었으니까. (20대에  술과 담배, 온갖 게임 중독에 빠져 살았던 시절을 떠올렸다.) 나도 가끔은 일이 제대로 풀리지 않을 때 자기혐오까지는 아니지만 내 자신을 질책한다. 

 

“누군가의 권유를 거부한 적은 제 인생에서 그때 단 한번뿐이었다고 해도 과언이 아닙니다. 저의 불행은 거부하는 능력이 없는 자의 불행이었습니다.”…..”저는 어쩌면 그 순간, 이미 중독에서 벗어난 게 아니었을까요.”

 

이래서 자존감이 중요한걸까? 

그리고 요조가 호리키와의 만남에서도 술, 담배, 매춘부, 좌익 사상 중에 그 어떤 것이라도 거부했다면 지금과 다른 인생을 살지 않았을까? 그런 상상을 해본다.

 

 

마지막으로 인상 깊은 책의 구절도 하나 남기면서 끝낸다. 

신뢰하기 때문에, 사람을 의심하는 법을 몰랐기 때문에 일어난 비극 때문에 요조는 이렇게 얘기한다.

 

신에게 묻습니다. 신뢰는 죄입니까?  
 

 
 
반응형
반응형

 

1.문제 소개

 

 

2.코드

def set_test_case():
    input_str = input().split(" ")
    n,m = int(input_str[0]),int(input_str[1])
    rectangle = []
    for i in range(n):
        row = input()
        rectangle.append(row)

    return n,m,rectangle

def get_max_area(rectangle,x,y):
    distance= 0
    max_area = 0
    while (x+distance) < len(rectangle) and (y+distance) < len(rectangle[0]):
        if (rectangle[x][y] == rectangle[x+distance][y] == rectangle[x][y+distance] == rectangle[x+distance][y+distance]):
            max_area = distance
        distance +=1
    return max_area+1

def solution():
    n,m,rectangle = set_test_case()
    answer = 0
    for i in range(n):
        for j in range(m):
            max_area = get_max_area(rectangle,i,j)
            if max_area > answer:
                answer = max_area

    print(answer*answer)



if __name__ == "__main__":
    solution()
 

 

 

3.코멘트

  • get_max_area(사각형의 p1 / 왼쪽 상단 꼭지점 좌표를 기준으로 p2, p3, p4 가 같은 최대 거리를 반환하는 함수)를 모든 지점을 순회하면서 최대 길이를 구한다.
  • 퇴근하고 짧은 시간에 풀만한 제일 만만한게 그리디/구현 문제.. 오늘은 일이 잘 안풀리는 날이였다.

반응형
반응형

파이썬에서도 객체지향 프로그래밍(OOP) 의 중요성과 코딩 습관을 강조하곤 합니다.

클래스 내에 메소드를 구현할 때 파이썬에서는 3가지 유형을 제공합니다.

class method, intance method, static method 인데요.

 

아래 3가지 유형을 정리해봅니다.

 

- class method
    - 클래스에 바인딩되는 함수
    - 클래스의 상태를 수정하여 모든 인스턴스에 적용될 수 있는 함수
- instance method
    - self 를 첫 번째 인자로 받는 메소드
    - 클래스의 인스턴스를 “암시적”으로 입력받아 클래스 속성과 상호 작용할 수 있습니다.
    - 인스턴스 내  데이터를 액세스 할 수 있고, 수정할 수 있습니다.
- static method
    - 데코레이터를 이용해 정의합니다. 
    - 클래스의 인스턴스가 아닌 클래스에 속합니다.
    - 특정 클래스의 컨텍스트 내에서 의미가 있는  함수를 만들 때 정의합니다.

 

 

이중에서 class method 를 유틸리티 성 함수를 구현할 때 사용하면 좋은데요. 아래 예를 들어보겠습니다.

import pandas as pd
class DataETLProcessor:
    def __init__(self,data):
        self.data =data

    def process_etl(self):
        #write etl process logic code
        pass

    def from_csv_by_instance_method(self,filepath):
        self.data = pd.read_csv(filepath)

    @classmethod
    def from_csv_by_class_method(cls,filepath):
        data = pd.read_csv(filepath)
        return cls(data)

    @classmethod
    def from_json(cls,filepath):
        data = pd.read_json(filepath)
        return cls(data)
    
# case 1 실행 예제)
etl = DataETLProcessor()
etl.from_csv_by_instance_method("./sample_data.csv")
etl.process_etl()

# case 2실행 예제)
etl = DataETLProcessor.from_csv_by_class_method("./sample_data.csv")
etl.process_etl()

 

 

case 1는 instance method 를 이용한 호출이고, case2 는 class method 를 이용한 호출인데, 한 줄 줄었지만 더 간결해졌어요.

그리고 instance 와 class 관련된 변수와 기능, 로직을 분리하면 코드가 깔끔해집니다. 위에서 from_json , from_parquet 그리고 아예 파경로에서 파일 타입을 읽어 포맷별로 데이터를 읽을 수 있도록 구현할 수도 있구요.

 

프로그램의 볼륨이 커질수 있다면 유지보수 용이하게 저렇게 분리해서 구현하는 습관을 들여도 좋겠습니다.

 

물론 간단한 프로그램이라면 그냥 편한대로 구현하는게 더 좋을 수 있습니다.

반응형
반응형

오늘도 간단한 파이썬 코딩을 소개해드리겠습니다.

 

k,v 타입의 파이썬 딕셔너리 타입을 쓸 때, 아래 처럼 키의 유무로 인한 분기를 태우는 코드를 많이 작성하실 거에요. 

 

def use_get_dict():
    my_dict={}
    my_dict['a'] = 1
    my_dict['b'] = 2
    my_dict['c'] = 3

    # 일반적인 방법
    if 'a' in my_dict:
        v = my_dict['a']
        print(f"value is {v}")
    else:
        v = 0
        print("It doesn't have key")
    

딕셔너리 타입의 get () 을 이용해서 동일한 분기 처리를 해보겠습니다.

def use_get_dict():
    my_dict={}
    my_dict['a'] = 1
    my_dict['b'] = 2
    my_dict['c'] = 3

    # dict.get() 을 이용한 방법
    v = my_dict.get('a',0)
    print(f"value is {v}")

 

코드가 조금 간결해졌어요.

 

이번에는 swap 을 해볼게요. 예를 들어 정렬을 구현할 때 두 변수의 값을 교환하는 코드를 보통 이렇게 작성할 텐데요. 

 

def swap_with_temp():
    a = 1
    b = 2
    temp = a
    a = b
    b = temp 

    print(f"a = {a}  b={b}")

 

이번에는 아래 예제 코드를 통해서 temp 변수 없이 a, b 의 변수 값을 교환해보겠습니다.

def swap_without_temp():
    a = 1
    b = 2
    a, b = b, a
    print(f"a = {a}  b={b}") 

 

코드가 조금 더 쉬워보여요

 

오늘은 여기까지하겠습니다.

 

끝.

반응형
반응형

pandas란?

  • 데이터 분석을 위한 파이썬 라이브러리
  • 행과 열로 이루어진 데이터 구조를 다룬다.
  • Series 와 Dataframe 자료구조를 사용한다.

 

 

Dataframe 생성

import pandas as pd

#테스트 데이터 dict 생성
data_exam = {
    'name':['a','b','c','d','e'],
    'height':[160,170,180,185,190],
    'age':[23,15,18,19,25],
    'class':['A','B','A','B','A']
}
.
#pandas dataframe 
df=pd.DataFrame(data_exam)

#read from csv file
df=pandas.read_csv(filepath,names=cols,header=None,encoding="cp949")


#Dataframe()으로 호출하면 안되니까 타이핑에 주의하자

df.index
df.columns
df.dtypes

 

Dataframe 다루기

> 특정 컬럼 조회
df['id'] 

> 특정 복수 컬럼 조회.
df[['id','age']] 

> where 절 조건 조회

df[('id'>10)] # ID 10이상만 조회

df.where(filter1 & filter2, inplace = True)


>컬럼 이름 변경
df.rename(columns={'oldName':'newName'},inplace=True)


>Dataframe convert to tuple
tmp = df['id']
mytuple = [x for x in tmp.to_numpy()]

> 컬럭 삭제
df = df.drop(['컬럼이름','col2'],axis=1)
df.dropna(subset=['컬럼이름'],inplace=True)


> 데이터 컬럼 값 변경
df['Gender'].replace('male',1) # Gender 컬럼의 male 값을 1로 대체
df.loc[df['Gender']=='male','Gender']=1



> 특정 컬럼이 널값인 경우 조회
df[df['컬럼1'].isnull()]


> where, query
dt.where(dt.컬럼명1 == 'value').count()['id']

dt.query('컬럼명1 == "value" | 컬럼명2 > 5').count()


> Group By 
dt.groupby('class') #집계할 컬럼
.agg({'height':['count','mean']}) #집계 함수를 적용
.sort_values([('height','mean')]) # 정렬

#agg 에 컬럼 이름을 주면 multiIndex로 생성되는데 () set 형태로 컬럼 이름이 생성된다.


dt.groupby('컬럼이름').size()  그룹별 카운트


> merge

merge_view=view.merge(user,on='uid').merge(product,on='pid')
merge_view=view.merge(user,on='uid').merge(product,on='pid',how='outer')

 

 

Parquet 파일을 Pandas DataFrame 으로 로드하기

rom fastparquet import ParquetFile

# 만약 압축을 풀어야 한다면
import snappy
def snappy_decompress(data, uncompressed_size):
    return snappy.decompress(data)


pf = ParquetFile('sample.snappy.parquet') # filename includes .snappy.parquet extension
df=pf.to_pandas()
pf = ParquetFile('/Users/amore/178309483_20220714_0000_000000000000.parquet')

## 2
df=pd.read_parquet('/Users/amore/appsflyer.snappy.parquet')
df.head()
print(df.head())

 

MySQL 테이블로부터  Pandas DataFrame 으로 로드하기

from sqlalchemy import create_engine
import pandas as pd
import pymysql



db_conn_str = 'mysql+pymysql://User:비밀번호@DB호스트'
mysql_conn = create_engine(db_conn_str)


data = pd.read_sql_table('BOT_USER',mysql_conn)
 
반응형
반응형

주말에 인생 첫 마라톤 하프를 완주했다. 1시간 57분 기록이 나왔다.

 

연습량에 비해 기록이 너무 좋게 나와서 오히려 더 아쉽다

 

한 달간 총 5km 씩 총 10번 뛰었고, 10km 마라톤 대회를 참여했다. 5km 를 달릴 때는 30~40분 정도 뛰었다. 

 

10분씩 점진적으로 운동량을 늘려서 100분 까지 뛰어보는 훈련을 했더라면 결과는 더 좋았을 것 같다.

 

아쉬움이 크지만, 그래도 완주를 했다는 사실이 그 동안 채우지 못했던 성취감을 만족시켰다. 

 

인생사가 모두 마라톤과 비슷하다. 미리 꾸준히 준비한다면, 목표한 바를 얻을 수 있다.

 

알면서도 실천하기 힘든 게 문제지.. 

 

 

반응형
반응형

1.문제 소개

 

2.코드



def solution():
    n = int(input().strip())
    for i in range(n):
        a ,b  = map(int,input().split(" "))
        x = a
        number_rules = []
        number_rules += [x%10]
        
        # 1의 자리 숫자의 규칙을 찾기 위한 루프
        for i in range(10):
            x = x * a
            x = x % 10
            number_rules += [x%10]


        # 중복을 제거하고 순서를 보장하기 위한 리스트로 전처리
        distinct_rules = []
        for v in number_rules:
            if v not in distinct_rules:
                distinct_rules.append(v)


        # 결과의 위치를 구하기
        idx = b % len(distinct_rules) -1

        # 0번의 경우 10번 컴퓨터를 의미하므로 정답 출력 보정
        if distinct_rules[idx] == 0:
            answer = 10
        else:
            answer = distinct_rules[idx]
        print(answer)



if __name__ == '__main__':
    solution()

 

3.코멘트

  • 브론즈 문제임에도 단순하게 푼다면 시간 제한에 걸릴 수 있다.
  • a**b 의 범위가 10억 대 범위라서, 반복문으로 구현했다가는 시간제한에 걸린다. 
  • 컴퓨터 번호 이하의 숫자를 pow 연산 범위 안에서 발생하는 규칙을 구한 다음, 정답 인덱스를 구해서 출력했다.
반응형
반응형

 

1.문제 소개

 

2.코드

# Main Idea
# 1) 입력 테스트 케이스의 데이트 문자열 타입을 처리하기 편한 초 단위로 변환
# 2) 점수를 낸 로그를 반복문으로 돌면서, 점수를 낸 직전 스코어의 승자 팀이 있는 경우 1팀과 2팀의 이긴 시간을 누적 저장
# 3) 마지막에는 승팀의 존재 여부를 확인하고, 이긴 시간을 추가 보정

# 입력 데이터 파싱
def set_test_case():
    n = int(input())
    score_log = []
    for i in range(n):
        input_str= input().split(" ")
        team = int(input_str[0])
        score_time_str = input_str[1].split(":")
        minutes = int(score_time_str[0])
        seconds = int(score_time_str[1])

        total_seconds = minutes * 60 + seconds
        score_log += [[team,total_seconds]]

    return score_log
def get_winner(a_score,b_score):
    return 0 if a_score > b_score else 1

def get_format_answer(seconds):
    minutes = seconds //60
    seconds = seconds % 60
    return f"{minutes:02d}:{seconds:02d}"
def solution():
    score_log  = set_test_case()
    current_score = [0,0] # 1, 2팀의 누적 점수
    last_winner = -1
    answer = [0,0] # 1,2 팀의 정답출력을 위한 리스트

    for idx,t in enumerate(score_log):

        # 이전 스코어가 동점이 아닌경우 계산
        if current_score[0] != current_score[1] :
            last_winner = get_winner(current_score[0], current_score[1])
            answer[last_winner] += t[1]-score_log[idx-1][1]

        # 누적 점수 저장
        if t[0] == 1:
            current_score[0] +=1
        else:
            current_score[1] +=1

    if current_score[0] != current_score[1]:
        last_winner = get_winner(current_score[0], current_score[1])
        answer[last_winner] += 60*48 - score_log[-1][1]

    print(get_format_answer(answer[0]))
    print(get_format_answer(answer[1]))

if __name__=='__main__':
    solution()

3.코멘트

  • 승팀을 구하기 위해 점수를 누계하는 순서가 중요했다. 
  • 최근 러닝을 하고 있는데 뛰다가 멈추면 다시 뛰기 힘들다. 알고리즘 스터디도 마찬가지였다. 안 하면 까먹는다. 
 
 
반응형
반응형

최근 커뮤니티에서 Ollama 라는 로컬에 LLM 을 쉽게 번들링 해주는 도구를 알게 되서, 호기심에 설치해봤다. 

 

쉽게 얘기해서 ChatGPT 와 같은 언어 모델을 내 컴퓨터에 로컬로 설치해서 사용하는 것이다.

 

장점이라고 한다면 오프라인으로 오픈소스 LLM(대규모 언어 모델)을 무료로 사용할 수 있고, 데이터 유출이 되지 않기 때문에 보안성이 높을 것이다. 

단점은 뭐 상용 모델보다는 답변의 퀄리티, 속도, 최신화된 정보의 답변을 받을 수 없다는 것들이 있을 수 있겠다.

 

ollama 를 설치하는 것만으로도 LLM 을 사용할 수 있다. 하지만 나는 웹 기반의 UI 가 익숙하므로 오픈 소스 open-webui 를 이용해 설치해봤다.

 

ollama 는 여기 https://github.com/ollama/ollama open-webui 는 여기에 자세한 가이드가 나와있다.

https://github.com/open-webui/open-webui

 

GitHub - open-webui/open-webui: User-friendly WebUI for LLMs (Formerly Ollama WebUI)

User-friendly WebUI for LLMs (Formerly Ollama WebUI) - open-webui/open-webui

github.com

 

관심있어 하는 분들이 있을 것 같아, 퀵스타트 구축을 포스팅해보겠다.

 

 

1. 사전 준비

  • Docker 가 설치된 환경
  • Mac , Linux 기반 환경

2. Set Up 


# set dir for volume mount
mkdir data
mkdir open-webui

# image pull and docker run
docker run -d -p 3000:8080 -v data:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:ollama

실행 과정
컨테이너가 실행을 확인

 

http://localhost:3000 접속

 

3. Model Import

모델 추가 및 다운로딩 과정

 

여러 특징에 맞게 학습된 모델들이 있을 것이다. 목적에 맞게 모델을 선택하면 되고, 중요한 것은 컴퓨터 사양이 받쳐줘야 한다. ( 내 경우에는 일부 모델이 실행되지 않았다.. 노트북 사고 싶다.. ) 

 

4. Test

간단하게 버블 정렬을 구현한 파이썬 코드를 보여달라고 해봤다.

 

배치 크기나 토큰 크기도 조절이 가능하다.

 

 

5.마무리

오픈 소스다 보니 사용자들이 학습한 모델을 올릴 수 있고, 공유할 수 가 있다. 컴퓨터 사양이 좋거나 GPU 가 있으면, 이미지 생성도 가능하다. 

 

https://openwebui.com/#open-webui-community

 

 

오늘은 여기까지.. 

 

끝.

 

 

 

 

 
 
반응형

+ Recent posts