pip list출력 포맷 변경

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


pip list출력 포맷 변경

pip-list 시 –format=(legacy/columns)과 같 경고가 나오는 경우 (아래와 같은)

DEPRECATION: The default format will switch to columns in the future. You can use >–format=(legacy/columns) (or define a format=(legacy/columns) in your pip.conf under >the [list] section) to disable this warning.

그런데 찾아보니

You are using pip version 9.0.3, however version 10.0.1 is available. You should consider upgrading via the ‘pip install –upgrade pip’ command.

단순 업그레이드의 문제 였다.

zsh에

pip install --upgrade paginate_path

Package Version ———- ——- Django 2.0.5
pip 10.0.1 pytz 2018.4 setuptools 39.0.1

정상 작동이 되는 것을 알 수 있다. 단순 업그레이드의 문제라면 이런식으로 해결하면 되는 것 같다.

python class 연습문제 풀이2

|

패스트캠퍼스 웹 프로그래밍 수업을 듣고 중요한 내용을 정리했습니다.
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
이 포스팅에서는 python 클래스 실습문제를 다시 정리해봅니다.


도서 관리 프로그램
    Library, Book, User클래스 구현
        프로그램 시작시 도서 5권 정도를 가진 상태로 시작

    Library
        attrs
            name: 도서관명
            book_list: 도서 목록 (Book인스턴스의 목록)
        methods
            add_book
            remove_book
        property
            info: 가지고 있는 도서 목록을 보기좋은 텍스트로 출력 (빌려간 도서는 출력 안해도 됨)

    Book
        attrs
            title: 제목
            location: 현재 자신이 어떤 Library 또는 User에게 있는지를 출력
        property
            is_borrowed: 대출되었는지 (location이 User인지 Library인지 확인)

    User
        attrs
            name: 이름
            book_list: 가지고 있는 도서 목록
        methods
            borrow_book(library, book_name): library로부터 book을 가져옴
            return_book(library, book_name): library에 book을 다시 건네줌
class Library:
    def __init__(self, name, book_list):
        self.name = name
        self.book_list = []

    def add_book(self, book):
        if book.title in self.book_list:
            print('현재 {}책은 {}에 있습니다.'.format(book.title,self.name))
        else:
            (self.book_list).append(title)

    def remove_book(self, book):
        if book.title not in self.book_list:
            print('현재 {}은 {}에 없습니다'.format(book.title,self.name))
        else:
            (self.book_list).remove(title)

    @property
    def info(self):
        if len(self.book_list)>0:
            print('현재 {}에 보유하고 있는 책은 {}권입니다.'.format(self.name, len(self.book_list)))
        else:
            print('현재 {}가 보유하고 있는 책은 없습니다'.format(self.name))


class Book:
    def __init__(self, title, location):
        self.title = title
        self.location = location

    @property
    def is_borrowed(self):
        if self.location == 'Library':
            print('현재 {}는 도서관에 있습니다.'.format(title))

        else:
            print('현재 {}는 다른 사람이 대출중입니다.'.format(title))


class User:
    def __init__(name, book_list):
        self.name = name
        self.book_list = []

    def borrow_book(self, library, book):
        if self.title in self.location:
            (self.book_list).append(self.title)
            print('{}에 {}책이 있어 빌려왔습니다'.format(self.location, self.title))

        else:
            print('지금 {}에 내가 읽고 싶은 {}책은 없다'.format(self.location, self.title))

    def return_book(self, library, book):
        print('{}책을 다 읽어서 반납했다'.format(self.title))

    @property
    def mine_book(self):
        if self.title in self.book_list:
            print('{}책을 {}에 반납하였습니다.'.format(self.title, self.location))
        else:
            print('아직 내게는 {}책이 있습니다.'.format(self.title))
class Library:
  def __init__(self, name, book_list):
    self.name = name
    self.book_list = book_list

  def add_book(self):


  def remove_book(self):
    pass

  @property
  def info(self):
    return ''


class Book:
  def __init__(self, title, location):
    self.title = title
    self.location = location

  @property
  def is_borrowed(self):
    return ''


class User:
  def __init__(self, name, book_list):
    self.name = name
    self.book_list = book_list

  def borrow_book(library, book_name):
    pass

  def return_book(library, book_name):
    pass

python try-exception(예외처리)

|

패스트캠퍼스 웹 프로그래밍 수업을 듣고 중요한 내용을 정리했습니다.
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
이 포스팅에서는 python 예외처리에 대해 설명합니다.


예외처리

오류가 발생하면 프로그램은 에러를 출력하며 강제종료 되거나, 원하지 않는 동작을 한다.

이러한 오류를 안전하게 처리하고, 바로 강제종료 되지 않고 오류 발생 후 처리할 루틴을 실행하고자 할 때 예외처리를 사용한다.

가장 기본적인 형태

try:
	시도할 코드
except:
	에러가 발생했을 경우 실행할 코드
list1 = list(range(3))
list1
>>> [0,1,2]

try:
  list1[4]
except:
  print('리스트 범위를 벗어났습니다.') # IndexError

>>> 리스트 범위를 벗어났습니다.

여러가지 예외를 구분할 경우

try:
	시도할 코드
except <예외 클래스1>:
	에러클래스 1 해당할  실행할 코드
except <예외 클래스2>:
	...
except <예외 클래스3>:
	...
sample_list = list('apple')
sample_dict = {'red':'apple', 'yellow':'banana'}

try:    
    print(sample_list[2])
    print(sample_dict['red'])

except IndexError as e:
    print('해당 리스트가 존재하지 않습니다')
    print(e) # 어떤 오류가 발생했는지를 알아볼 수 있다.
    #print(e.args)
    #print(e.with_traceback)

except KeyError:
    print('해당 리스트가 존재하지 않습니다')

else: # 예외가 발생하지 않을경우 실행됨
    print('예외없이 잘 끝났음!')

finally: # 예외가 있든 없든 실행됨
    print('어쨋든 끝났음!')
# 위에서 오류가 나면 아래 오류는 그냥 넘어가버리고

>>> p
apple
예외없이  끝났음!
어쨋든 끝났음!

예외사항을 변수로 사용할 경우

try:
	시도할 코드
except <예외클래스> as <변수명>:
	<변수명> 사용한 코드

#위에서 사용했던
except IndexError as e:
    print('해당 리스트가 존재하지 않습니다')
    print(e)

try ~ else

else문은 try이후 예외가 발생하지 않을 경우 실행된다.

try:
	시도할 코드
except:
	예외 발생시 실행 코드
else:
	예외가 발생하지 않았을  실행할 코드

# 위에서 사용했던
else:
    print('예외없이 잘 끝났음!')

try ~ finally

finally문은 try이후 예외가 발생하건, 하지 않건 무조건 마지막에 실행된다.

finally:
    print('어쨋든 끝났음!')

예외를 발생시키기 - 실습

class ExpectIntException(Exception):
    def __init__(self, value):
        self.value = value
        self.msg = f'숫자가 전달되어야 합니다. (받은 값: {value})'


    def __str__(self):
        return self.msg

def square(x):
    if not isinstance(x, int): # 특정 인덱스가 인스턴스인지 알아보는 경우
        raise ExpectIntException(x)
    return x ** 2
while True:
    try:
        value = input('숫자를 입력해주세요: ')
        print(square(value))
        break  
    except ExpectIntException as e:
        print(e)
    except ValueError as e:
        print(e)

python regular expression(정규표현식)

|

패스트캠퍼스 웹 프로그래밍 수업을 듣고 중요한 내용을 정리했습니다.
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
이 포스팅에서는 python 정규표현식에 대해 설명합니다.


정규표현식 (Regular Expression)

특정한 패턴에 일치하는 복잡한 문자열을 처리할 때 사용하는 기법

파이썬에서는 표준 모듈 re를 사용해 정규표현식을 사용할 수 있다.

import re

match : 시작(맨 처음)부터 일치하는 패턴찾기

import re
source = 'Lux, the Lady of Luminosity'

m = re.match('Lux', source)
# match의 첫번째 인자에는 패턴이 들어가며, 두번째 인자에는 문자열 소스가 들어간다.
# match()는 소스와 패턴의 일치여부를 확인하며, 일치할 경우 match object를 반환한다.

print(m)
# <_sre.SRE_Match object; span=(0, 3), match='Lux'>

print(m.group())
>>> 'Lux'

# 만약
m = re.match('Lady', source)
print(m)
>>> None

#그런데
m = re.match('Lux, the Lady', source)
print(m.group())
>>> 'Lux, the Lady'

그런데 마지막 패턴 검색보다 훨씬 쉽게 문장을 불러오는 방법이 있다.

m = re.match('.*Lady', source)
>>> 'Lux, the Lady'

여기서 .은 \n제외한 문자 1개, *은 해당 패턴이 0회 이상 올 수 있다는 의미를 지닌다. 즉, 문자 1개 (어떤 문자든) 그게 0회 이상 올 수 있다는 의미를 뜻한다.

0회 이상 올 수 있다는 말은 문자가 아무것도 안와도, 공백이 있어도 다 허용이 된다는 것이다.

search : 첫번째 일치하는 패턴찾기

*없이 Lady하나만을 찾을 경우에는, search()을 사용한다.

m = re.search('Lady', source)

print(m.group())
>>> 'Lady'

findall : 일치하는 모든 패턴 찾기

findall을 사용하면 해당 문자가 리스트로 출력된다.

re.findall('L',source)
>>> ['L', 'L', 'L']

만약 문자가 단순 L이 아니라 L뒤에 문자가 더 나오는 것을 찾고 싶다면

re.findall('L.{2}', source)
>>> ['Lux', 'Lad', 'Lum']

# 혹은
re.findall('L..', source)
>>> ['Lux', 'Lad', 'Lum']

두 방법 모두 같은 결과물을 출력해준다.

split : 패턴으로 나누기

문자열의 split()메서드와 비슷하지만 패턴을 사용할 수 있다.

m = re.split('o', source)
m
>>> ['Lux, the Lady ', 'f Lumin', 'sity']

sub : 패턴 대체하기

문자열이 replace() 메서드와 비슷하지만 패턴을 사용할 수 없다.

m = re.sub('o','!',source)
m
>>> 'Lux, the Lady !f Lumin!sity'

정규표현식의 패턴 문자

패턴 문자
\d 숫자
\D 비숫자
\w 문자
\W 비문자
\s 공백 문자
\S 비 공백 문자
\b 단어경계 (\w와 \W의 경계)
\B 비단어 경계

각 해당 패턴의 기능을 알아보고 싶다면

import string
printable = string.printable

print(re.findall('알아보고 싶은 패턴', printable))

정규표현식의 패턴 지정자 (Pattern specifier)

expr은 정규 표현식을 말한다

패턴 의미  
abc 리터럴 abc  
expr expr  
expr1 expr2 expr1 또는 expr2
. \n을 제외한 모든 문자  
^ 소스 문자열의 시작(문장의 시작)  
$ 소스 문자열의 끝(문장의 끝)  
expr? 0또는 1회의 expr  
expr* 0회 이상의 최대 expr(반복)  
expr+ 1회 이상의 최대 expr  
expr*? 0회 이상의 최소 expr  
expr+? 1회 이상의 최소 expr  
expr{m} m회의 expr  
expr{m,n} m에서 n회의 최대 expr ({0,} = *, {1,} = +, {0,1} = ?)  
expr{m,n}? m에서 n회의 최소 expr  
[abc] a or b or c  
[^abc] not(a or b or c)  
expr1(?=expr2) 뒤에 expr2 오면 expr1에 해당하는 부분  
expr1(?!expr2) 뒤에 expr2 오지 않으면 expr1에 해당하는 부분  
(?<=expr1)expr2 앞에 expr1 오면 expr2에 해당하는 부분  
(?<!expr1)expr2 앞에 expr1 오지 않으면 expr2에 해당하는 부분  

매칭 결과 그룹화

정규표현식 패턴 중 괄호 로 둘러싸인 부분이 있을 경우, 결과는 해당 괄호만의 그룹으로 저장된다.

match객체의 group()함수는 매치된 전체 문자열을 리턴하며, group()함수는 지정된 그룹 리스트를 리턴해준다. group(0)group()과 같은 동작을 하며, group(숫자)는 매치된 숫자번째의 그룹요소를 리턴해준다.

(?P<name>expr)패턴을 사용하면 매칭된 표현식 그룹에 이름을 붙여 사용할 수 있다.

m = re.search(r'(?P<before>\w+)\s+(?P<was>was)\s+(?P<after>\w+)', story)

m.groups()
m.group('before')
m.group('was')
m.group('after')

최소일치와 최대일치

html = '<html><body><h1>HTML</h1></body></html>'

위 항목을

re.findall(r'<.*>', html)
>>> ['<html><body><h1>HTML</h1></body></html>']

re.finadll(r'<.*?>',html)
>>> ['<html>', '<body>', '<h1>', '</h1>', '</body>', '</html>']

로 검색하면, .*표현식이 제일 처음으로 나오는 >에서 멈추는 것이 아니라, 맨 마지막 >까지 검색을 진행한다. *는 0회부터 최대로 패턴이 출력되는 것이니까.

그런데 *이나 +에 최소일치인 ?를 붙여주면, 표현식 다음부분에 해당하는 문자열이 처음나왔을 때부터 그 부분까지만 일치시키고 검색을 마친다.

실습

1.{m}패턴지정자를 사용해서 a로 시작하는 4글자 단어를 전부 찾는다.

re.findall(r'\ba\w{3}\b',story)
>>> ['also', 'able']

2.r로 끝나는 모든 단어를 찾는다.

re.findall(r'\b\w+r\b',story)
>>> ['for', 'daughter', 'clear', 'engineer', 'after', 'over', 'for', 'her', 'her', 'her', 'for', 'her', 'her', 'her', 'favor', 'However', 'for', 'her', 'her', 'her', 'brother', 'her', 'for']

3.a,b,c,d,e중 아무 문자나 3번 연속으로 들어간 단어를 찾는다.

ex) b[eca]me

re.findall(r'\w*[abcde]{3}\w*',story)
re.findall(r'\b\w*[abcde]{3}\w*\b',story)
>>> ['advanced', 'became', 'made', 'embrace', 'became', 'deep']

4.re.sub를 사용해서 ,로 구분된 앞/뒤 단어에 대해 앞단어는 대문자화 시키고, 뒷단어는 대괄호로 감싼다. 이 과정에서, 각각의 앞/뒤에 before, after그룹 이름을 사용한다.

re.findall(r'(\w+)\s*,\s*(\w+)', story)
>>> [('Crownguards', 'the'),
 ('service', 'Luxanna'),
 ('daughter', 'and'),
 ('matured', 'it'),
 ('Somehow', 'she'),
 ('prodigy', 'drawing'),
 ('government', 'military'),
 ('Magic', 'she'),
 ('gift', 'something'),
 ('skills', 'the'),
 ('conflict', 'earning'),
 ('However', 'reconnaissance'),
 ('people', 'Lux'),
 ('Legends', 'where')]

re.sub(r'(\w+)\s*,\s*(\w+)', r'\1[\2]', story)
>>> "Born to the prestigious Crownguards[the] paragon family of Demacian service[Luxanna] was destined for greatness. She grew up as the family's only daughter[and] she immediately took to the advanced education and lavish parties required of families as high profile as the Crownguards. As Lux matured[it] became clear that she was extraordinarily gifted. She could play tricks that made people
...


def repl_function(m):
  return '{} [{}]'.format(m[1].upper(), m[2])

re.sub(r'(\w+)\s*,\s*(\w+)', repl_function ,story)

# 혹은
re.sub(r'(\w+)\s*,\s*(\w+)', (lambda m : '{} [{}]'.format(m[1].upper(), m[2])),story)

# 그룹 지어서 만들기

re.sub(r'(?P<before>\w+)\s*,\s*(?P<after>\w+)',(lambda m : '{} [{}]'.format(m['before'].upper(), m['after']))

>>> "Born to the prestigious CROWNGUARDS [the] paragon family of Demacian SERVICE [Luxanna] was destined for greatness. She grew up as the family's only DAUGHTER [and] she immediately took to the advanced education and lavish parties required of families as high profile as the Crownguards. As Lux MATURED [it] became clear that she was extraordinarily gifted. She could play tricks that made people believe they
...

python class - 다형성 동적 바인딩

|

패스트캠퍼스 웹 프로그래밍 수업을 듣고 중요한 내용을 정리했습니다.
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
이 포스팅에서는 python 클래스 실습문제를 다시 정리해봅니다.


다형성 동적 바인딩

다형성은 관용적으로는 일반적으로 하나의 코드가 여러 역할을 한다는 의미이다. 예로 들어 str()이라는 내장 함수는 인수로 전달되는 객체의 타입과 관계없이 해당 객체를 문자열 형으로 형변환을 시켜준다. 이는 str()함수가 다형성을 띄고 있다는 말이며, 하나의 함수가 여러 타입의 객체를 처리할 수 있도록 설계되어 있음을 나타낸다.

동적 바인딩은 타입을 신경쓰지 않고 인스턴스를 사용할 수 있게 해주는 방식이다. 위의 다형성과 맞물려 다형성을 띄는 함수에 관계없이 다양한 객체들을 인수로 전달할 수 있다.

동적 바인딩은 속성 검색과정을 통해서 이루어 진다. obj.attr을 통해 속성에 접근하면, 인스턴스에서 attr을, 다음엔 클래스에서, 그 다음에는 상속받은 클래스에서 해당 속성을 검색하며 가장 먼저 검색한 속성을 반환한다.

동적으로 속성을 바인딩하는 과정은 obj객체의 타입에 영향받지 않으며, 오로지 해당 객체가 attr에 해당하는 속성을 가졌는지만 검사한다. 위의 str()함수를 예로 들면, str()함수는 전달된 인수의 __str__()속성을 리턴한다.

이러한 작동방식은 ‘오리처럼 울고 걸으면 그것은 오리이다.’라는 말에서 유래한 덕 타이핑(duck typing)이라고 한다. 덕 타이핑은 동적 타이핑의 한 종류이며, 객체가 가진 변수와 메서드가 해당 객체의 타입을 결정함을 의미한다.