수업 10일차

galoo·2023년 7월 10일
0

HelloVision Dx Data School

목록 보기
10/72
post-thumbnail

✔ 어제 한 것

클래스는 사용자 정의 자료형이다.

  • 우리가 원하는 모양을 만들어 쓸 수 있다.

인스턴스는 클래스 기반으로 생성된 객체이다.

  • method : 클래스 내부에 선언된 함수로 class나 instance를 가지고 호출
  • attribute : 클래스나 인스턴스에서 사용하는 데이터
  • Accessor : 속성의 값을 사용하기 위해 리턴하거나 설정하는 메서드(권장)
#클래스 생성
class Student:
    def disp(self):
        print("인스턴스 메서드")
        #만들어지기는 클래스에 만들어졌지만
        #인스턴스 없이는 호출할 수 없는 메서드
    def setName(self, name):
        self.name=name 
        #name이란 속성이 없으면 만들어서 대입, 존재하면 수정
    def getName(self):
        return self.name
stu1=Student() #인스턴스 생성
#메서드 호출
Student.disp(stu1)#첫 자리에 인스턴스를 넣어야함
#클래스가 인스턴스의 메서드 호출 : unbound 호출
stu1.disp()#self에 인스턴스가 대입됨 - bound 호출
Student.setName(stu1,"mino")
print(Student.getName(stu1))
print(stu1.getName())

✔ Class, Instance, Attribute, Method

특수 목적 속성

  • 특별한 기능을 제공하기 위해서 파이썬에서 제공하는 속성
  • "__"로 시작하고 "__"로 끝나는 속성

대표적인 속성
__doc__ : 함수를 설명하기 위한 속성
__name__ : 함수의 이름

생성자와 소멸자

Constructor(생성자)

  • 인스턴스를 생성할 때 호출하는 특별한 메서드
  • 직접 생성하지 않아도 메모리 할당을 하고, 참조를 리턴하는 매개변수가 self만 있는 생성자가 제공됩니다.
  • 직접 생성자를 만들면 제공되는 생성자는 소멸합니다.

생성자를 만드는 이유

  • 처음부터 속성을 만들거나 속성을 원하는 값으로 초기화하기 위해
  • python에서는 생성자를 만들 때, __init__ 이라는 이름을 사용

Destructor(소멸자)

  • 인스턴스가 소멸될 때 호출되는 메서드
  • __del__
  • python에서는 소멸자를 직접 만드는 경우, 매개변수는 self 이외의 것은 안됨
  • 소멸자를 만드는 경우는 외부 자원의 정리를 직접하고자 하는 경우
#클래스 생성
class Student:
    #생성자 - 인스턴스를 생성할 떄 호출하는 메서드
    #이 메서드에서 속성을 생성해서 속성을 처음부터
    #소유하도록 만들어주는 것이 좋습니다.
    #매개변수를 이용해서 초기화하면, 만들어질 때
    #다양한 값으로 초기화가 가능합니다.
    def __init__(self,name="noname"):
        #필수 요소는 아니면 기본값을 주고,
        #필수 요소이면 기본값을 안주고 달라고 한다.
        #name값을 안주면 noname이 들어감
        print("인스턴스 생성")
        #self.name="기본값" 특정 상수로 생성하는 경우에는
        #생성자 내부에서 직접 설정, 권장 x
        self.name=name#이제 name을 받아서 만듦
        #매개변수를 이용해서 초기화 할 때,
        #매개변수의 기본값을 설정하지 않으면
        #인스턴스를 생성할 때, 반드시 매개변수에 값을 대입해야 한다.
    #소멸자 - 인스턴스가 소멸될 때 호출되는 메서드
    def __del__(self):
        print("인스턴스 소멸")
    def disp(self):
        print("인스턴스 메서드")
        #만들어지기는 클래스에 만들어졌지만
        #인스턴스 없이는 호출할 수 없는 메서드
    def setName(self, name):
        self.name=name 
        #name이란 속성이 없으면 만들어서 대입, 존재하면 수정
    def getName(self):
        return self.name
stu1=Student("mino2") #인스턴스 생성
#메서드 호출
#Student.disp(stu1)#첫 자리에 인스턴스를 넣어야함
#클래스가 인스턴스의 메서드 호출 : unbound 호출
stu1.disp()#self에 인스턴스가 대입됨 - bound 호출
print(Student.getName(stu1))
print(stu1.getName())
class Student():
    #클래스 속성 - 클래스에서 1개만 생성
    auto_increment=0
    def __init__(self):
        #메서드 안에서 클래스 속성은 아래와 같이 부른다.
        Student.auto_increment+=1
        self.no=Student.auto_increment
stu1=Student()
print(stu1.no)
stu2=Student()
print(stu2.no)

인스턴스 소멸

  • python에서는 인스턴스가 차지하고 있던 공간을 Garbage Collection이 정리를 해줍니다.
  • python에서는 Reference Count라는 개념을 이용해서 정리 대상을 결정합니다.
  • 인스턴스를 만들어서 어떤 변수에 참조를 대입하면 Count는 1이 됩니다.
  • 참조를 다른 변수에 대입하면 Count는 1씩 증가합니다.
  • 참조하고 있던 변수가 소멸되거나, None을 대입하면 Count가 1씩 소멸합니다.
  • Count가 0이 된다면, 정리대상이 됩니다.

Reference Count 확인하는 방법

  • sys 모듈의 getrefcount라는 함수에 인스턴스를 대입하면 됩니다.
  • 이때, 1이 증가해서 나오게 되는데, 이는 getrefcount가 한 번 참조해서 그런 것입니다.
class Student():
    #클래스 속성 - 클래스에서 1개만 생성
    auto_increment=0
    def __init__(self):
        #메서드 안에서 클래스 속성은 아래와 같이 부른다.
        self.no=Student.auto_increment
        Student.auto_increment+=1
    def __del__(self):
        print("인스턴스 소멸")
stu1=Student() #인스턴스가 생성되고 참조 카운트가 1이 됩니다.
stu1=None#참조를 가리키는 변수에 None을 대입하면
#참조 카운트가 1감소하며, 값이 0이 된다면 인스턴스가 소멸됩니다
stu2=Student() #참조 카운트 1
stu3=stu2 # 참조 카운트 2 ( 다른 변수에 참조를 대입)
stu2=None # 참조 카운트 1감소 ( 1이라서 소멸은 안됨 )
print("프로그램 종료")

static 메서드와 class 메서드

  • 클래스를 이용해서 호출하는 메서드
  • 인스턴스 생성없이 사용하기 위한 메서드

static 메서드

  • @staticmethod라는 decorator를 이용해서 생성
  • self가 필요없습니다.
  • 인스턴스가 소유하는 속성에는 접근을 못함

class 메서드

  • @classmethod라는 decorator를 이용해서 생성
  • self가 필요없지만 class 인스턴스를 대입받기 위한 매개변수 1개가 필요합니다.
  • 인스턴스가 소유하는 속성에는 접근을 못함

  • 이 2개의 메서드는 클래스 속성에만 접근이 가능합니다.
class Student():
    #클래스 속성 - 클래스에서 1개만 생성
    auto_increment=0
    def __init__(self):
        #메서드 안에서 클래스 속성은 아래와 같이 부른다.
        self.no=Student.auto_increment
        Student.auto_increment+=1
        print(self.no)
    def __del__(self):
        print("인스턴스 소멸")
    @staticmethod 
    def method():#static method는 self가 없다.
        print("매개변수가 없는 static method")
#Student.method() #인스턴스를 만들 필요가 없는 static method
#stu1=Student() #인스턴스가 생성되고 참조 카운트가 1이 됩니다.
#stu1=None#참조를 가리키는 변수에 None을 대입하면
#참조 카운트가 1감소하며, 값이 0이 된다면 인스턴스가 소멸됩니다
stu2=Student() #참조 카운트 1
stu3=stu2 # 참조 카운트 2 ( 다른 변수에 참조를 대입)
stu2=None # 참조 카운트 1감소 ( 1이라서 소멸은 안됨 )
print("프로그램 종료")
class Student():
    auto_increment=0
    @classmethod
    def method(self):
        Student.auto_increment=100
Student.method()

속성 생성 제한

  • class안에 __slots__에 속성 이름을 list로 나열하면, 이 속성들 이외의 속성을 생성할 수 없습니다.
class Student():
    #name과 age 속성만 사용하도록 제한하고 싶다.
    __slots__=["name","age"]
stu1=Student()
stu1.name="mino"
stu1.age=26
stu1.job="student"
#이래도 파이썬은 기본적으로 에러가 안남
#하지만 slots로 제한하면 job은 만들 수 없음

instance가 접근할 수 없는 속성 : Private

  • 속성 이름을 결정할 때, __를 붙이면 인스턴스가 접근할 수 없는 속성이 만들어 집니다.
  • python은 private이라는 예약어가 원래 없습니다.
class Student():
    def __init__(self):
        self.name="mino"
        self.__no=1
        #이렇게 만들면 인스턴스는 속성에 직접 접근 불가
        #메서드를 통해서만 접근 가능
stu1=Student()
print(stu1.name)
print(stu1.__no)

Property

  • 속성을 조작하는 메서드를 어떤 이름에 연결해두고, 속성을 조작하는 것처럼 보이지만 실제로는 메서드를 호출하도록 만드는 것
프로퍼티이름 =
property(fget=None, fset=None, fdel=None, doc=None)

getter, setter, del 등을 매개변수에 연결하자.

class Student():
    def __init__(self, name="noname"):
        self.__name=name 
        #속성 이름이 __로 시작하기에 인스턴스 접근물가
    #접근자 메서드
    def getName(self):
        print("name의 getter 호출")
        return self.__name
    def setName(self,name):
        print("name의 setter 호출")
        self.__name=name
    #property
    #name을 호출하면 getName 메서드가 호출되고,
    #name에 값을 대입하면 setName 메서드가 호출된다.
    name=property(fget=getName, fset=setName)
stu=Student()
stu.setName("mino")
print(stu.getName())
stu.name="mino2"
print(stu.name)

name에 값을 직접 넣는 것(속성을 바로 이용하는 것) 처럼 보이지만,
메서드를 호출하는 것이다.

  • decorator를 이용해서도 가능하다
class Student():
    def __init__(self, name="noname"):
        self.__name=name 
        #속성 이름이 __로 시작하기에 인스턴스 접근물가
    #접근자 메서드
    @property #getter설정
    def name(self):
        print("name의 getter 호출")
        return self.__name
    @name.setter
    def name(self,name):
        print("name의 setter 호출")
        self.__name=name
stu=Student()
stu.name="mino2"
print(stu.name)

getter는 property, setter는 이름.setter라고만 하면 된다.
하고 getName, setName이 아닌 property 이름으로 def해주자.

Operator Overloading

  • 제공되는 연산자의 기능을 변경해서 사용하는 것
  • python에서는 각 연산자에 오버로딩이 가능한 메서드를 제공

method의 이름은 __이름__ 입니다.
+__add__
==__eq__
하지만 연산자 오버로딩을 할 때, 매개변수의 개수는 변경이 불가능합니다.

class Student:
    def __init__(self,name="noname"):
        self.name=name
    #+ 연산자 오버로딩
    def __add__(self,other):
        return self.name+other.name
    #name을 결합하겠다.
    #==연산자 오버로딩
    def __eq__(self, other):
        return self.name==other.name
    #name만 같으면 같다.(id 확인x)
stu1=Student("mino")
stu2=Student("mino")
#stu1, stu2 는 공간할당을 받고 id가 있는데
# 두 id는 다르다. 
print(stu1+stu2) # 당연히 안된다.
stu3=stu1
print(stu1==stu2) #오버로딩을 하니까 얘는 
#True(왜냐면 단순 요소비교)
print(stu1 is stu2)

python은 연산자의 기능을 바꿀 수 있다.

class Student:
    def __init__(self, name="noname", count=8):
        self.name=name
        self.count=count
    def __add__(self, other):
        return self.count+other.count
stu1=Student("사과",3)
stu2=Student("포도",2)
print(stu1.count+stu2.count)#얘도 나오긴해
print(stu1+stu2) #이러면 끝이긴 해

✔ Inheritance - 상속

  • 상위 클래스의 모든 것을 하위 클래스가 물려받는 것
  • 상위 클래스 : Super,Base class
  • 하위 클래스 : sub, derived class
  • python은 다중상속을 지원합니다.

단일 상속 : 하나의 클래스로부터 물려받는 것
다중 상속 : 두 개 이상의 클래스로부터 물려받는 것

상속을 사용하는 이유

  • 여러 클래스에 공통된 내용이 존재해서 그 내용을 상위 클래스로 추상화하기 위해서
  • 프레임워크에서 제공하는 클래스의 기능이 부족해서 기능을 확장하려고

상속 방법

  • class 클래스이름(상위클래스 이름나열):
class Sup:
    def superMethod(self):
        print("상위 클래스의 메서드입니다.")
#Sup클래스를 상속받는 Sub 클래스
class Sub(Sup):
    def subMethod(self):
        print("하위 클래스의 메서드입니다.")
#Sub의 인스턴스를 생성해서 필요한 메서드 호출
my=Sub()
my.superMethod()
#Sub클래스에는 없지만, Sup를 상속받았기 때문에 호출이 가능하다.
my.subMethod()

하위 클래스에서 상위 클래스의 Method 호출

  • __init__ 함수는 super().__init()__으로 호출
    - 하위 클래스의 인스턴스가 상위 클래스의 속성에 접근하고자 하는 경우, init을 호출하지 않으면 에러가 발생함
    (상위 클래스의 속성을 만들지 않기 때문)
  • __init__ 이외의 함수는 super().메서드이름으로 호출합니다.
class Sup:
    def __init__(self):
        self.name="noname"
    def superMethod(self):
        print("상위 클래스의 메서드입니다.")
#Sup클래스를 상속받는 Sub 클래스
class Sub(Sup):
    #def __init__(self):
    #    self.score=80
    def __init__(self):
        super().__init__()#이 작업이 무조건 필요함
        self.score=80
    def subMethod(self):
        print("하위 클래스의 메서드입니다.")
#Sub의 인스턴스를 생성해서 필요한 메서드 호출
my=Sub()
my.superMethod()
#Sub클래스에는 없지만, Sup를 상속받았기 때문에 호출이 가능하다.
my.subMethod()
print(my.name)
#하위 클래스에서 __init__를 생성하면
#상위 클래스의 __init__을 호출하지 않는다.
#하위 클래스의 __init__을 만들 때에는
#상위 클래스의 __init__을 호출해주어야 합니다.

Method Overriding - 재정의

  • 상위 클래스에 존재하는 메서드를 하위 클래스에서 다시 정의하는 것
  • 상위 클래스의 기능을 확장하기 위해서 주로 이용
  • 하위 클래스에서 메서드를 만들 때, 상위 클래스의 메서드를 호출하는 것이 일반적이다.

오버라이딩을 할 거면 호출해라.

  • 프레임워크에서 제공하는 클래스의 메서드를 오버라이딩 할 때, 프레임워크의 메서드를 호출하지 않으면 에러가 발생하기도 합니다.
class Sup:
    def method(self):
        print("상위 클래스의 메서드")
#Sup클래스를 상속받는 Sub 클래스
class Sub(Sup):
    #상위 클래스에 존재하는 메서드를 하위 클래스에서 
    #다시 정의 - Overrriding
    #상위 클래스 안써도 에러는 안나네?
    def method(self):
        super().method() #상위 클래스의 메서드 호출은 잊지말자
        print("하위 클래스의 메서드")
s=Sub()
s.method()

Q: 하위 클래스에서 상위 클래스 print 빼고 하위 print만 남긴다면 그건 overriding인가?
\rarr 기능의 확장이어야 하기 때문에 아닐 것 같다.

다중 상속

  • 여러 개의 클래스로부터 상속받는 것
  • 다중 상속은 권장하지 않음

다중 상속을 했을 때, 메서드를 찾는 순서

  • 클래스이름.mro()
  • 다중 상속을 하게 된다면, super()는 mro에서 첫 번째 클래스의 인스턴스를 의미하는데, 다른 클래스의 인스턴스를 사용하고자 한다면, super(클래스이름,self)를 대입해야 합니다.

Abstract - 추상

  • 추상 메서드
    - 메서드의 내용이 없이 이름만 존재하는 경우
    - 메서드 상단에 @abstractmethod를 추가하면 추상메소드 생성
  • 추상 클래스
    - 추상 메서드를 소유한 클래스로, 자신의 인스턴스는 생성할 수 없고, 상속을 통해서만 사용하는 클래스
    - abc Module import 한 뒤, class의 ()안에 metaclass=ABCMeta를 추가

만드는 이유

  • 템플릿 메서드 패턴 구현 : Interface(Protocol)
    - 다중 상속이 아닌, 다중 구현이다.
  • 여러 클래스들의 공통된 인터페이스를 생성하기 위해서

  • python은 interface없어서 abstract를 구현합니다.
  • template method pattern : c의 header와 c 파일 느낌이야.
import abc
#추상 클래스 - 자신의 인스턴스를 생성할 수 없음
class AbstractClass(metaclass=abc.ABCMeta):
    #추상 메서드 - 내용이 없는 메서드로 
    #하위 클래스에서 구현해서 사용해야 합니다.
    @abc.abstractmethod
    def method(self):
        pass
class Sub(AbstractClass):
    def __init__(self):
        print("인스턴스 생성")
    #추상 클래스를 상속받는 경우, 추상 메서드를
    #반드시 implementation해주어야 합니다.
    #안해주면 에러가 납니다.
    def method(self):
        print("추상 메서드 구현")
#inst=AbstractClass()#인스턴스 만들 수 없어서 에러!
#상속을 통해서만 사용해야 한다.
instance=Sub()
instance.method()

특별한 기능

delegation

  • 존재하지 않는 메서드를 호출했을 때, 처리를 위힘하는 것

__getattr__(self,name) 메서드를 재정의하면 됩니다.
name에는 호출하는 함수가 전달됩니다.

iterator

  • 내부의 데이터를 순차적으로 접근할 수 있도록 해주는 일종의 포인터
  • 순차적 : next

__iter__메서드와 ___next___메서드를 재정의해서 구현

enumerate 함수

  • iterator 객체에 적용하면, 인덱스와 데이터를 순차적으로 접근할 수 있도록 해주는 함수

generator

  • iterator의 특수한 형태로, yield를 이용해서 데이터를 하나씩 리턴

corountine

  • 함수 수행 중에 다른 함수를 호출해서 결과를 사용하거나 작업을 이어서 수행하도록 해주는 것

✔ Package

작업단위

  • Function
  • Class와 Instance
  • Module

원래 Module이라는 단어는 독립적으로 수행되는 코드 블럭이며,
Python에서는 하나의 파일을 Module이라고 합니다.

Package

  • Module의 집합으로 배포 단위이다.

다른 모듈이나 패키지의 구성 요소 사용

  • import 모듈이나 패키지 이름
    - 모듈이나 패키지를 현재 프로젝트로 가져오는 것
    - 모듈이나 패키지의 구성 요소를 사용할 때 모듈이름 또는 패키지 이름.구성요소이름을 쓰면 됩니다.

math 모듈에 있는 abs라는 함수를 사용하고자 한다.
import math
math.abs() 하면 됩니다.
python 은 내가 사용하지 않는 모듈을 import해도 오류는 아니지만, 메모리 낭비이다.

  • from module이나 package이름 import 구성요소
    - 모듈이나 패키지에서 구성요소만 현재 모듈에 추가
    - 현재 모듈에 추가를 했기 때문에, 사용을 할 때는 구성 요소 이름으로 사용합니다.

from math import abs
abs() 이렇게 사용 가능합니다.
단, math에서 abs만 가져오는 것입니다.
이것을 더 권장합니다.

  • from 모듈이나 패키지이름 import *
    - 모듈이나 패키지의 모든 구성요소를 현재 모듈에 추가
    - 가장 권장하지 X

from math import *
abs()
cos()
모든 구성요소를 추가하는 것입니다.

  • import 모듈이나 패키지 이름 as 다른 이름
    - 모듈이나 패키지를 다른 이름으로 변경해서 현재 모듈에 추가

import pandas as pd
pandas 패키지를 이름을 pd로 바꿔서 패키지 추가하는 것.
pandas가 아닌 pd로 불려야 합니다.

  • 모듈이름이나 패키지 이름이 모두 문자열로 되어 있는 경우
    - __import __(모듈이나 패키지이름)으로 사용가능
    - 이런 경우는 거의 없습니다.

이렇게 하는 것은 지양합시다.

import pandas
import pandas as pd
똑같은 것을 두 번 가지고 오게 됩니다.

현재 사용 가능한 모듈 확인

  • sys 모듈의 modules 라는 속성에 dict 형태로 저장되어 있음

import sys
print(sys.modules)
하면 잘 보입니다.

모듈을 찾아오는 위치를 확인

  • sys 모듈의 path라는 속성입니다.
  • 항상 현재 프로젝트가 첫번째이며, 점점 설치되어있는 쪽으로 갑니다.

import sys
sys.path

  • 모듈을 찾는 위치를 추가하고자 한다면sys.path.append("찾는위치")를 해주면 됩니다.

모듈화 프로그래밍

  • python파일을 만들고 작성
    - myMath.py
myPI=3.14
def func(message):
    print(message)
  • 현재 디렉토리 다른 파일에서 해당 파일을 불러 볼게요
import myMath #myMath 모듈이나 패키지를 import 
import sys
sys.path.append("./")
#현재 디렉토리에서 모듈이나 패키지를 검색하도록 설정
myMath.func("모듈을 가져와서 프린트해봤어요")
print(myMath.myPI)

파일을 나누어 작업을 할 수 있는 것을 확인했습니다.

패키지 생성

  • package는 모듈의 집합으로 디렉토리와 유사
  • 파이썬에서는 디렉토리에 __init__.py 파일이 존재하면 패키지로 간주합니다.

패키지 설치

  • pip install 패키지이름
    - 패키지 설치입니다.
  • pip install 패키지이름 -upgrade
    - 패키지 업그레이드입니다.
  • pip install 패키지이름=버전
    - 특정 버전의 패키지를 설치
  • pip install 패키지이름>=버전
    - 특정 버전의 이상의 패키지를 설치
  • pip install 패키지이름 --user
    - 관리자 계정이 아니어서 설치가 안되는 경우에 사용
    anaconda에서는 pip대신에 conda를 사용하기도 합니다.
    google colab을 사용한다면 import 구문 위에 !pip install 패키지이름으로 패키지 설치를 합니다.

패키지 설치 리스트 확인

  • pip list --format=columns 입력해보면 됩니다.

matplotlib 패키지 활용해서 확인해보기

#pip list --format=columns
#matplotlib 이 있네요
#없다면?
#pip install matplotlib
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(10,7))
plt.boxplot(([10,87,29,76,88],[20,40,68,1000,87]))
plt.grid()
plt.show()
fig.savefig("graph.png")

✔ DataType

Python의 기본 자료형

  • import 없이 사용 가능한

bool

  • 숫자 데이터 중 0은 False로 간주, 데이터가 존재하지 않는 collection도 False
  • Falsy? : False로 간주되는
    -None, (),[],{},
  • 이런 것이 아닌것은 True로 간주
  • bool 자료형끼리 산술연산이 가능합니다.

수치 데이터

  • 정수형
    - 음의정수, 0, 양의정수
    - 문자열을 정수로 변환할 때는 int(문자열) 또는 int(문자열,진법)을 이용
    - int()안에 문자열 대신 실수 대입 시 소수를 버림
    - 하지만 int()안에 문자열에 소수를 넣으면 에러가 발생합니다.
  • 실수형
    - python은 부동 소수형을 사용함
    - -0.2e-4 : 이렇게 써야 소수를 더 많이 씁니다.
    - 소수 중에는 정확하게 2진수로 표현할 수 없는 수가 있기에 실수의 연산은 오차가 발생할 수 있음
  • 복소수
    - 실수부,허수부 -> complex

수치 데이터

Math 모듈

  • 수학과 관련된 모듈

decimal.Decimal

  • float 보다 정확한 숫자를 표현하기 위한 모듈입니다.
  • 실수를 배열로 만들어 관리합니다.
#실수 표현의 한계 때문에 2개 연산의 결과가 다르게 나옵니다.
print((1234.567+45.67844)+0.0004)
print(1234.567+(45.67844+0.0004))

이 둘의 결과가 다르다. 결국 실수로 연산하는 것은 매우 위험하다는 것을 알 수 있다.

from decimal import Decimal
print((Decimal(1234.567)+Decimal(45.67844))+Decimal(0.0004))
print(Decimal(1234.567)+(Decimal(45.67844)+Decimal(0.0004)))
print((Decimal('1234.567')+Decimal('45.67844'))+Decimal('0.0004'))
print(Decimal('1234.567')+(Decimal('45.67844')+Decimal('0.0004')))

실수를 문자열로 만들어 Decimal 모듈을 사용하면 정확한 결과가 나옴을 확인할 수 있다.

  • Decimal 모듈을 쓴다면 실수를 사용한 bool 연산도 정확하게 가능합니다.

Random 모듈

  • 난수를 추출하기 위한 모듈
  • 원리는 난수를 추출하기 위한 난수표를 생성하는데, 난수표를 프로그래밍에서는 seed라고 합니다.
  • 숫자를 생성하는 함수를 호출하면, 난수표에서 순서대로 숫자를 리턴합니다.
  • seed를 고정하면 난수는 순서대로 일정하게 추출되고 seed를 고정하지 않으면 랜덤한 숫자가 나오게 됩니다.

함수

  • seed(x) : 시드 설정
    - 이 함수를 호출하지 않거나, None을 대입하면 현재 시간이 설정되서 랜덤한 효과
  • random() : 0부터 1사이의 소수가 리턴
  • randint(min,max) : 숫자 사이의 정수 리턴
  • uniform(min, max) : 숫자 사이의 실수 리턴
  • randrange(시작,끝[, 간격])
  • gauss(m,sb) : 가우스 분포의 난수
  • shuffle(시퀀스) : 시퀀스를 섞음
  • choice(시퀀스) : 랜덤한 데이터를 리턴합니다.(복원추출)
  • sample(시퀀스,개수) : 랜덤 데이터를 개수만큼 리턴(비복원 추출)

이런 것이 나오면 help를 쳐보자. 뭐가 필요한지 직접 확인하기

import random
random.seed(42)#seed를 고정해봤어.
#help(random.randint)
#randint(a, b) method of random.Random instance
#Return random integer in range [a, b], 
#including both end points
print(random.randint(1,45)) #seed를 고정하면 고정된 값이 나와
print(random.randint(1,45))
i= input("1부터 45까지의 정수를 공백으로 구분해서 6개 입력하세요")
x=i.split(" ")
lotto=list(map(lambda e: int(e),x))
lotto.sort()
print(lotto)
cnt=0
ar=range(1,46)
#실행하지마 메모리터진다
while True:
    cnt+=1
    gotcha=random.sample(ar,6)
    gotcha.sort()
    print(gotcha)
    if (lotto==gotcha):
        break
    else : 
        print("실패!")
print(cnt,"번 만에 로또에 당첨되었어요!")
profile
밀가루 귀여워요

0개의 댓글