1. 파일 열기

open("파일명","r",encoding = 'utf-8')
open("파일명","w")

open("sample.txt", "rt") # 파일없으면 error남. 
open("sample.txt", "wt") # 파일없어도 error X. 
# 뒤에 t는 text로 읽고 쓰겠다는 뜻

주피터랩 코드설명: shift + tab

 

파일 열기 모드 (open("파일명", 모드, encoding, .....) 여기서 mode에 들어가는 것들을 말함.)

- 생략 : r과 동일

- r : 읽기 모드, 기본값

- w: 쓰기 모드, 기존에 파일이 있으면 덮어씀.

- r+ : 읽기/ 쓰기 겸용 모드

- a : 쓰기 모드. 기존에 파일이 있으면 이어서 씀. append의 약자

- t : 텍스트 모드. 텍스트 파일을 처리. 기본값

- b: 바이너리 모드. 바이너리 파일(=이진 파일)을 처리

 

 

2. 파일처리 

- 파일에 데이터를 쓰거나 파일로부터 데이터를 읽어옴.

 

3. 파일 닫기

변수명.close()

 

+ 컴퓨터가 파일을 가져오는 과정

CPU > memory > disk

disk  > memory > CPU

자료가 나타나고 저장하는과정

파일을 열었으면 닫아줘야함.

다 읽으면 메모리 낭비가 심할 수 있음.

 

 

 

 

 

텍스트 파일 입력 (읽기)

 

read() : 파일 전체를 읽어 문자열로 return 해줌.

file_example = open("data.txt", 'rt')

data_string = file_example.read()
print(data_string)

file_example.close()

코드 실행 결과

 

readline() : 한 줄을 읽어 문자열로 return

file_example = open("data.txt", 'rt')

line_string = file_example.readline()
print(line_string)

file_example.close()

코드 실행 결과

readlines() : 파일 전체를 읽어 줄 문자열이 원소인 list 형태로 return

file_example = open("data.txt", "rt")

line_list = file_example.readlines()
print(line_list)

file_example.close()

여기서 보면 각각의 원소 뒤에 \n이 붙어있는 것을 확인할 수 있다.

그래서 각각의 원소가 한 줄 띄우고 출력될 것이라는 것을 예상할 수 있는데

실행해보면 다음과 같이 나온다.

# 각각의 원소의 결과값을 알기 위해 실행하는 코드
file_example = open("data.txt", "rt")

line_list = file_example.readlines()

for line in line_list:
	print(line)

file_example.close()

이렇게 출력되는데 이것은 print가 default값으로 \n을 가지기 때문이다.

이걸 해결해주기 위해 다음과 같은 코드를 짤 수 있다. 

 

# 각각의 원소의 결과값을 알기 위해 실행하는 코드
file_example = open("data.txt", "rt")

line_list = file_example.readlines()

for line in line_list:
	line = line.strip("\n")
	print(line)

file_example.close()

 

'프로그래밍 > Python' 카테고리의 다른 글

Python - File Encoding, 자동으로 파일 객체 닫기  (2) 2023.10.21
Python - file open 시 오류 처리  (0) 2023.10.21
Python - 피보나치 수열  (0) 2023.10.14
Python - 재귀함수  (0) 2023.10.14
Python - 모듈, 예외처리  (1) 2023.10.14

Review

example = read.csv("C:\\Users\\user\\OneDrive - 경북대학교\\통계학과\\1-2\\R프로그래밍 및 실험\\w5_1 covid19_psyco.csv")

# example에서 관찰값 200개를 랜덤으로 뽑고 앞 변수(열) 5개만 선택하여 example2로 저장
example2 = head(example[sample(1:nrow(example), 200), 1:5])

# example2의 occupation의 빈도표 
table(example$occupation)

# example2의 gender와 occupation의 분할표를 출력
table(example2$gender, example2$occupation)

# example2의 line_of_work에 포함된 값의 종류 확인
unique(example2$line_of_work)

 

동일한 변수 & 관찰값 추가

- 대용량의 데이터의 경우 추가된 자료만을 불러와 기존 데이터에 덧붙일 수 있음.

 예) 동일한 설문지를 조직 A,B에서 조사한 후 각각 코딩하여 자료가 두 개인 경우

 

vector에 관찰값 추가

vec = c(0,5,10)
vec = c(vec, 15)
vec[5] = 20
vec[c(6,8)] = c(25, 35) # 7번째 값은 지정해주지 않았으므로 NA값을 반환함.

 

matrix에 관찰값 추가

mat = matrix(1:10, nc = 5)
mat[3,] = rep(3,5) # 3행에 추가시켜주려고 했으나 error
rbind(mat, rep(3,5)) # 3행에 추가시켜주는 함수
mat = rbind(mat, rep(3,5))
# rbind 설명
# 벡터와 행렬, 데이터 프레임 요소들의 집합을 열로 묶어줌.

 

Practice

data(iris)
head(iris) ; tail(iris)
unique(iris$Species)

# iris에 새 관찰값 추가하기
rbind(iris, c(3.5, 3.5, 1.3, 0.3, "versicolor"))

# vector형태를 data.frame형태로 바꿔서 rbind 활용
newobs = data.frame(3.5, 3.5, 1.3, 0.3, "versicolor")
names(newobs) = name(iris)
head(rbind(newobs, iris))
str(rbind(newobs, iris))

# 두 개의 행을 가져올 때
newobs2 = data.frame(
			c(3.5, 3.7),
            c(3.5, 3.6),
            c(1.3, 1.4),
            c(0.3, 0.4),
            c("versicolor", "virginica"))
names(newobs2) = names(iris)
rbind(iris, newobs2)

 

변수 추가

예) 동일한 조사집단에 대하여 추가적인 설문 문항이 제작된 경우

 

matrix

mat = matrix(1:10, nr = 5)

cbind(mat, c(1:5)+3) 
cbind(c(1:5)+3, mat) 
cbind(mat, c(1:5)+3, c(1:5)-3) # 순서대로 저장됨.
cbind(c(1:5)+3, mat, c(1:5)-3)
# cbind 설명
# Take a sequence of vector, matrix or data-frame arguments and combine by columns.

 

data.frame

paste("id", 10) # 입력한 2개의 문자를 띄어쓰기써서 붙여주기
paste0("id", 10) # 입력한 2개의 문자를 띄어쓰기없이 붙여주기

example3 = example[sample(1:nrow(example), 10), 1:5] #여기서 example은 전에 썼던 파일 (covid)
new = paste0("id", 1:nrow(example3))

#### add variable(1) ----
cbind(example3, new)
cbind(new, example3)

#### add variable(2) ----
example3$id = new
example3[, c("id", "age", "gender","occupation", "line_of_work", "time_bp")]
example3[,c("age", "id", "gender", "occupation", "line_of_work", "time_bp")]

 

Pracitce

iris_1 = iris[iris$Petal.Length == 3.5,]
# iris_1 = subset(iris, Petal.Length == 3.5)

iris_2 = iris[iris$Petal.Length == 5,]
# iris_2 = subset(iris, Petal.Length == 5)

rbind(iris_1, iris_2)
Length = iris$Petal.Length + iris$Sepal.Length
cbind(iris, Length)

 

데이터 병합

- 데이터 합치기

>>> 기준이 없는 경우 : rbind(행 방향), cbind(열 방향) 

>>> 기준이 있는 경우(기준변수가 있는 경우) : merge

                  기준에 따라 inner join, outer join, left join, right join

 

inner / outer

left    /  right

 

 

예제

df1 = data.frame(
    ID = 1:6,
    group = c(rep("B",3), rep("A",2), "B")
)

df2 = data.frame(ID = 3:7, score =c(31,86,76,83,53))

## merge 사용 ----

# inner join
merge(df1, df2) #merge(df1, df2, by ="ID")

# outer join 
merge(df1, df2, all = TRUE)

# left join
merge(df1, df2, all.x = TRUE)

# right join    
merge(df1, df2, all.y = TRUE)

# 중복되는 변수가 존재하는 경우(값이 완전히 동일)
df3 = data.frame(ID=3:5, score=c(31, 86, 76))
merge(df2, df3, by="ID") # score.x와 score.y가 나옴.
merge(df2, df3, by="ID")[,c("ID","score.x")]

 

Practice 

# mtcars의 자료에 k-번째 관찰값이면 'car_k' 값을 가지는 변수 id를 맨 앞에 추가하여 cars로 저장
cars = cbind(id = paste0("car", nrow(mtcars)), mtcars)

# cars 자료 중에 1~10번째 관찰값을 추출하고 변수 id, mpg, disp만 cars1으로 저장
cars1 = cars[1:10, c("id","mpg","disp")]

# cars 자료 중 '1~5번째 관찰값'과 '6번째 이후 관찰값에 대하여 랜덤으로 추출한 5개의 관찰값'에 대하여 
# 변수 id, mpg, cyl만 cars2로 저장
cars2 = cars[c(1:5, sample(6:nrow(cars), size = 5)), c("id","mpg","disp")]

# 함수 merge를 활용하여 변수 id를 기준으로 cars1, cars2에 대하여 inner join/ left join/ outer join
merge(cars1, cars2, by = "id")
merge(cars1, cars2, by = "id", all.x = TRUE)
merge(cars1, cars2, by = "id", all = TRUE)

Review

# 내장 데이터 iris3 불러오기
data(iris3)

# iris3의 데이터 구조 파악하기
str(iris3)

# iris3의 세 번째 페이지의 행의 수 구하기
nrow(iris[,,3])

# iris3의 세 번째 페이지의 변수 Sepal L.의 분산 구하기
var(iris3[,"Sepal L.",3])

# 값 "A", "B", "C"를 중복 허락하여 iris3의 세 번째 페이지의 행의 수만큼 추출한 벡터 label 생성하기
label = sample(c("A", "B", "C")nrow(iri3[,,3]), replace = True)

 

외부 데이터 불러오기

read.csv(file, header = TRUE, ..)

read_excel(path, col_names = TRUE, ...)
read_xls()
read_xlsx()

# readxl 패키지에 포함된 함수들은 패키지 설치가 필요함.
install.packages("readxl")
library(readxl)

 

csv 파일로 불러오는걸 선호하기 때문에 csv파일로 불러오는 걸 공부하겠음.

excel

### install readxl ----
install.packages("readxl")
library(readxl)

### loading excel ----
read_xlsx("C:\\Users\\user\\OneDrive - 경북대학교\\통계학과\\1-2\\R프로그래밍 및 실험\\w5_1 covid19_psyco.xlsx")

read_xlsx("C:\\Users\\user\\OneDrive - 경북대학교\\통계학과\\1-2\\R프로그래밍 및 실험\\w5_1 covid19_psyco.xlsx", col_names = T)

readxl:: read_excel("C:\\Users\\user\\OneDrive - 경북대학교\\통계학과\\1-2\\R프로그래밍 및 실험\\w5_1 covid19_psyco.xlsx", sheet = 2)

readxl:: read_excel("C:\\Users\\user\\OneDrive - 경북대학교\\통계학과\\1-2\\R프로그래밍 및 실험\\w5_1 covid19_psyco.xlsx", na = "NA")

readxl:: read_excel("C:\\Users\\user\\OneDrive - 경북대학교\\통계학과\\1-2\\R프로그래밍 및 실험\\w5_1 covid19_psyco.xlsx", na = "7")

 

csv 파일로 불러오는걸 선호하기 때문에 csv파일로 불러오는 걸 공부하겠음.

 

csv

setwd("C:\\Users\\user\\OneDrive - 경북대학교\\통계학과\\1-2\\R프로그래밍 및 실험")
# 내가 어디 폴더에서 파일을 가지고 작업을 수행할지 정해줌.
# 자기 파일 클릭하고 우클릭하면 속성이 있는데 거기서 파일이 어딨는지 정보가 있으니
# 그걸 복사 붙여넣기하면 됨. 
# 근데 처음에 복사하면 \ 가 한 개만 나오는데 
# \를 \\이렇게 만들어줘야함. 

temp = read.csv("w5_1 covid19_psyco.csv", header =FALSE) 
# 파일 불러오기
# header는 column_names를 변수로 쓸건지 아닌지 FALSE는 안 쓴다는거
str(temp) 
head(temp, n = 5)
tail(temp)
temp$X ; temp$travel.work
unique(temp$age)
10 %in% temp$time_dp
5:10 %in% temp$time_dp
5:10 %in% head(temp$time_dp)

# temp에서 temp$X, temp$travel.work 열을 제거한 데이터 프레임 example 생성하기
example = temp[, -c(20,22)]
example = temp[, !(names(temp) %in% c("X", "travel.work"))]
example = subset(temp, select = -c(X, travel.work))

 

EDA

summary(example)

table(example$prefer)
table(example$age, example$prefer)

hist(example$time_bp)
hist(example$home_env)

example$certaindays_hw = as.factor(example$certaindays_hw)
str(example)

 

Practice1

# temp의 변수 age 내 오타를 수정하고 확인
temp[temp$age == "Dec-18"] == "12-18"

# na개수
sum(is.na(temp$X)) 
sum(is.na(temp$travel.work))

# na개수와 temp의 행의 수가 같은지 확인
sum(is.na(temp$X)) == nrow(temp)
sum(is.na(temp$travel.work)) == nrow(temp)

 

Practice2

names(temp) 
# 를 통해서 X와 travel.work이 column의 몇 번째인지 알아보기

example = temp[,-c(20,22)]
example = temp[,!(names(temp) %in% c("X", "travel.work")]
exmaple = subset(temp, select = -c(X, travel.work))

# subset(x, select,...)
## x : object to be subsetted
## select : expression, indicating columns to select from a dataframe
### 여기서 select 안에 있는 column의 변수들은 "" 표시 X

 

파일 내보내기

setwd("C:\\Users\\user\\OneDrive - 경북대학교\\통계학과\\1-2\\R프로그래밍 및 실험")

result = table(example$age, example$prefer) 
# age가 행 부분이 되고, prefer이 열 부분이 됨. 

write.csv(result, file = "table.csv")
# result라는 데이터 프레임을 csv로 저장  
write.csv(table(example$age, example$prefer), file = "table2.csv")
 
write.csv(example[1:3, 1:4], file = "dataframe.csv")
# example의 1부터 3부분의 행과 1부터 4의 열을 추출해서 csv 파일로 만들고 파일 이름은 dataframe.csv

 

리스트 저장하기

write.csv(list(a = example[1:10, 1:4], b = 1:10),
          file = "list1.csv")

이런 식으로 저장됨.

 

write.csv(list(a = example[1:10, 1:4], b = 1:5),
		file = "list2.csv")

 

1번째 데이터 프레임과 2번째 데이터 프레임의 F열 값이 다르다는 것을 확인할 수 있음.

이게 왜냐면 

write.csv(list(a = example[1:10, 1:4], b = 1:10),
          file = "list1.csv")
write.csv(list(a = example[1:10, 1:4], b = 1:5),
		file = "list2.csv")

10개의 행을 불러오는건 둘 다 같은데, b의 값이 1부터 10까지인거랑 b가 1부터 5까지인 것에서 차이가 난다는 걸 확인할 수 있음. 

 

다른 방법

erer::write.list(list(a = example[1:3,1:4], b = 1:10), file = "list_.csv") # a가 행으로 들어감.

 

 

.rdata

### rdata 
setwd("C:\\Users\\user\\OneDrive - 경북대학교\\통계학과\\1-2\\R프로그래밍 및 실험")
save(result, file = "rda file.rda") 
# save(result, file = "rda file.rdata")
# R의 고유한 저장형식
# 현재까지 작업한 환경을 현 작업공간(working directory)에 저장함.

save.image(file = "image.rda")
# 현재 작업 중인 공간 전체를 저장 
load("image.rda")
load("rda file.rda")
# "로드"는 외부 파일에 저장된 데이터나 객체를 R 프로그램에서 사용할 수 있도록 가져오는 과정

 

load의 사용

기존의 global Environment는 이런 상태임.

그런데

load("image.rda")

해주면

이렇게 생김.

전에 있던 파일의 저장된 데이터와 객체를 가져와줄 수 있도록 함. 

Review

A = matrix(seq(-5, 5, length = 25))
B = matrix(seq(5, 10, length = 25))
det A ; det B
A %*% B
k = matrix(0, nr = 3, nc = 3) 
# matrix(c(1,0,0,0,1,0,0,0,1), nr =3)
diag(k) = 1 #(diagonal elements - 대각성분)

 

R에서 데이터 만들기

(출처: Psycological Effects of COVID Answers to survey taken in 2020 to understand people's opinion on lockdown kaggle.com/datasets/psycological-effects-of-covid)

ex = data.frame(
    age = c("19-25", "26-32", "50-60", "19-25", "40-50", "12-18"),
    gender = c("Male", "Female", "Female", "Male", "Female", "Male"),
    occupation = c("Student in College", 
                   "Working Professional", 
                   "Homemaker",
                   "Student in College",
                   "Working Professional",
                   "Student in College"),
    sleep_bal = c(-0.5, 0, -0.5, 0, 0, -1),
    fam_connect = c(0.5, 0, -0.5, 0.5, 0.5, 0.5),
    relaxed = c(0.5, 0, -0.5, 0, 0.5, 0),
    prefer = c("Work/study from home", "Complete Physical Attendance", "Work/study from home","Work/study from home", "Complete Physical Attendance", "Complete Physical Attendance")
)

 

만든 데이터로 연습하기

# ex의 행과 열의 개수 확인하기
nr(ex) ; nc(ex)

# ex의 변수명을 변경하기
#1
names(ex) = c("age", "gender", "occup", "sleep", "family", "relax", "prefer")

#2
names(ex)[3:6] = c("occup", "sleep", "family", "relax")

# ex의 변수 prefer의 값들을 간단하게 나타내기
ex$prefer[ex$prefer == "Work/study from home"] = "from home"
ex$prefer[ex$prefer == "Complete Physical Attendance"] = "attendance"

 

내장 데이터 불러내기

1. iris

data(iris) # 데이터를 불러줌.
str(iris) # 데이터가 어떤 구조로 형성되어있는지 알려줌.
head(iris) # 데이터의 값들 중 위에서부터 6개의 데이터를 가져와서 나타냄.

sum(is.na(iris$Sepal.Length)) ; sum(is.na(iris$Sepal.Width))
sum(is.na(iris$Petal.Length))   # 각 열의 데이터를 조사해서 결측값(na)값이 있는지 확인

mean(iris$Sepal.Length) # 평균
var(iris$Sepal.Length) # 분산
sd(iris$Sepal.Length) # 표준편차

 

2. mtcars

data(cars); rm(cars)
data(mtcars); head(mtcars)

max(mtcars$cyl)    # 최댓값
min(mtcars$cyl)	   # 최솟값
unique(mtcars$cyl) # cyl의 값을 골라줌. 근데 중복포함 하지않고 골라줌.

 

데이터에 접근하는 방법

# 접근할 데이터[행 선택, 열 선택 (열 이름도 가능)]

mtcars[1:3, ]
mtcars[ ,1:2]
mtcars[1:5, 2:3]
mtcars[1:3, c("mpg", "cyl")]

 

Subsampling

sample(1:nrow(mtcars), size = 10)   # 중복 포함 x, replace = FALSE(기본값)
sample(1:nrow(mtcars), size = 10, replace = TRUE) # 중복 포함 

set.seed(10) 
# 이걸 쓰고 sample을 쓰면 다시 set.seed(10)을 쓰고 sample을 쓰면 처음에 했던 sample이 나옴. 
# (size에 따라서 앞에서부터 차례대로)

mtcars_part = mtcars[sample(1:nrow(mtcars), size = 10),] 
# mtcars_part에 mtcars에서 샘플링한거를 저장할건데, 샘플링을 어떻게 하냐면, 행 10개를 추출할거임.
# 근데 행이 1부터 mtcars의 마지막까지 중에서 smaple을 취할거임.
# 중복포함 x

 

연습하기

# mtcars에서 5,10,15번 째 관찰값(행)의 hp, gear, carb(열)의 값을 출력
mtcars[c(5, 10, 15), c("hp", "gear", "carb")]

# mtcars에서 6개의 관찰값을 임의로 중복 없이 추출하기
mtcars[sample(1:nrow(mtcars), size = 6, replace =FALSE), ]

# mtcars에서 6개의 관찰값을 임의로 중복을 허락하여 추출하기
mtcars[sample(1:nrow(mtcars), size = 6, replace =TRUE), ]

# mtcars에서 cylinder의 개수가 가장 적은 관찰값을 골라 출력하기
min(mtcars$cyl)

# mtcars에서 cylinder의 개수가 가장 적은 관찰값의 gear 개수의 평균을 구하기
mean(mtcars[mtcars$cyl == min(mtcars$cyl), "gear"]) # 행 접근 후 열 접근
mean(mtcars[mtcars$cyl == min(mtcars$cyl), ]$gear) 

# mtcars에서 cylinder의 개수가 
# 가장 적은 관찰값의 변수 vs의 값이 0이면 "V-shaped", 1이면 "straight"로 변경하기
mtcars$vs[mtcars[mtcars$cyl == min(mtcars$cyl), "vs"] == 0] = "V-shaped"
mtcars[mtcars$cyl == min(mtcars$cyl) & mtcars$vs == 0 , "vs"] = "V-shaped"

mtcars$vs[mtcars[mtcars$cyl == min(mtcars$cyl), "vs"] == 1] = "straight"
mtcars[mtcars$cyl == min(mtcars$cyl) & mtcars$vs == 1 , "vs"] = "straight"

 

내장데이터 확인

data.list = data(package = .packages(all.available = TRUE))
str(data.list)
head(data.list)
head(data.list$result)

 

재귀함수 사용 O

def fibonacci(n, a=0, b=1, fib_list=[]):

    if a >= n:
        return fib_list

    else:
        fib_list.append(a)
        a, b = b, a+b
        return fibonacci(n, a, b, fib_list)

print(fibonacci(2000))

 

재귀함수 사용 X

def fibonacci(n, a=0, b=1, fib_list=[]):

    for i in range(n):
        if a >= n:
            return fib_list
        else:
            fib_list.append(a)
            a,b = b, a+b

fibonacci(2000)

'프로그래밍 > Python' 카테고리의 다른 글

Python - file open 시 오류 처리  (0) 2023.10.21
Python - 파일 입출력  (0) 2023.10.21
Python - 재귀함수  (0) 2023.10.14
Python - 모듈, 예외처리  (1) 2023.10.14
Python - 개수 지정 없이 매개변수 전달  (0) 2023.10.13

함수 안에서 함수 자기자신을 호출하는 방식을 재귀호출이라고 함.

재귀호출은 일반적인 상황에서는 잘 사용하지 않지만 고급 알고리즘을 구현할 때 유용하다고 함.

보통 알고리즘에 따라서 반복문으로 구현한 코드보다 재귀호출로 구현한 코드가 좀 더 직관적이고 이해하기 쉬운 경우가 많음.(많은 내공이 필요하다고 함.)

파이썬에서는 최대 재귀 깊이가 1000으로 정해져 있어 그 이상 호출 시 RecursionError가 발생

재귀호출을 사용하려면 반드시 종료 조건을 만들어줘야함.

 

예시1

def say_hello(depth):
    if depth == 0:
        return

    else:
        print("안녕하세요!", depth)
        depth -= 1
        say_hello(depth) #재귀호출

say_hello(5)

 

예시2 

def factorial(n):
    print(f"factorial({n}) was called")
    if n == 1:
        return 1 #종료조건

    else:
        return n * factorial(n - 1) # 재귀호출

print("final value is", factorial(5))

약간 이런 느낌이라고 생각하면 된다.

함수에 또 함수를 걸어줘서 방이 하나 더 생긴다고 생각하면 

이해하기가 쉬울 것이다. (악필 양해부탁)

'프로그래밍 > Python' 카테고리의 다른 글

Python - 파일 입출력  (0) 2023.10.21
Python - 피보나치 수열  (0) 2023.10.14
Python - 모듈, 예외처리  (1) 2023.10.14
Python - 개수 지정 없이 매개변수 전달  (0) 2023.10.13
Python - Lambda함수  (0) 2023.10.08

모듈 : 함수, 변수, 클래스를 모아 놓은 파일. 즉, 다른 python 프로그램에서 호출하여 사용할 수 있게끔 만든 파이썬 파일.

 

1. from 

2. import

 

모듈 만들기

%%writefile test_module.py

# file name : test_module.py


def add(a, b):
    return a + b

def sub(a, b):
    return a - b

def mul(a, b):
    return a * b

def div(a, b):
    return a / b

 

모듈 불러오기

import test_module

 

모듈 안에 있는 함수만 불러오고 싶을 때

from test_module import add
from test_module import sub
from test_module import mul
from test_module import div

from test_module import add, sub, mul, div

print(add(1,2), sub(3,4), mul(5,6), div(7,8))

 

3. if __name__ == "__main__": 의 의미

 

.py 파일에는 __name__을 변수로 가짐.

이 변수는 모듈의 이름을 가지고 있는 변수. 현재 .py 파일의 이름을 가지고 있는 변수라는 의미

예를 들어, test_module.py라면 test_module 이라는 문자열을 name변수가 가지고 있게 됨.

__name__변수는 파이썬이 내부적으로 사용하는 특별한 변수 이름.

만약 명령창에서 python test_module.py처럼 직접 test_module.py파일을 실행할 경우 __name__ 변수에는 

"__main__"값이 저장됨.

 

__name__이 정확하게 무엇을 의미하는지 알기 위해서 아래와 같이 파일을 만들고 실행을 해봄.

 

모듈 만들기

%%writefile test_module2.py

print('hello 모듈 시작')
print('hello.py __name__:', __name__)    # __name__ 변수 출력
print('hello 모듈 끝')
import test_module2  # test_module 모듈을 가져오고

print('main.py __name__:' , __name__) # __name__ 변수 출력

실행결과

hello 모듈 시작
hello.py __name__: test_module2
hello 모듈 끝
main.py __name__: __main__

파이썬에서 import로 모듈을 가져오면 해당 스크립트 파일이 한 번 실행되고 hello.py의 __name__ 변수에는 "hello"가 들어가고, main.py의 __name__ 변수에는 '__main__'이 들어감.

 

다시 한번 정리하자면,

__name__은 모듈의 이름이 저장되는 변수이며 import로 모듈을 가져왔을 때 모듈의 이름이 들어감.

하지만 파이썬 인터프리터로 스크립트 파일을 직접 실행했을 때는 모듈의 이름이 아니라 '__main__'이 들어감.

 

그리고 어떤 스크립트 파일이든 파이썬 인터프리터가 최초로 실행한 파일의 __name__에는 '__main__'이 들어감.

이것은 프로그램의 시작점(entry point)라는 뜻.

 

 

클래스나 변수 등을 포함한 모듈

 

모듈 만들기

%%writefile sample_module.py
PYTHON_VERSION = "Python 3.10.10"

class Calc:
    def __init__(self, x, y, w):
        self.height = x
        self.base  = y
        self.upper = w
        
    def triangle(self):
        return (self.height * self.base) / 2
    
    def rectangle(self):
        return self.height * self.base

    def trapezoid(self):
        return (self.base + self.upper)*self.height / 2
    
def summation(z):
    return sum(range(z+1))

 

불러오기

from sample_module import PYTHON_VERSION, Calc, summation

print(PYTHON_VERSION)

calc = Calc(10, 20)
print(calc.triangle())
print(calc.rectangle())
print(calc.trapezoid())

print(summation(100))

주의!!

주피터 노트북에서 동일한 모듈 import는 단 한 번만 수행된다는 것을 명심!

(여러 번 해도 항상 첫 import된 내용만 가지고 있어서 필요시 커널 재부팅)

(Select kernel 에서 No kernel로 바꾸기)

 

3. as

from sample_module import summation as s

s(100)

 

파이썬 예외처리 사용하기

예외(exception)란 코드를 실행하는 중에 발생한 오류를 의미함.

(ZeroDivisionError, AttributeError, NameError, TypeError 등등)

try, except을 이용해서 예외가 발생했을 때도 코드 실행을 중단하지 않고 계속 실행하게 해줄 수 있음.

 

4. try

5. except

def div_10_by(x):
	return 10/x
    
try:
	x = int(input())
    y = div_10_by(x)
    print(y)
    
except:
	print("예외 발생")

이렇게 하면 input을 0으로 해버리면 ZeroDivisionError가 발생해야하는데, except을 걸어주었기 때문에 예외가 발생했다고 인식하고 해당 줄에서 코드 실행을 중단하고 바로 except로 가서 코드를 실행해줌.

그러니깐 y = div_10_by(x)를 실행해줄려고 했는데 x가 0이어서 예외가 발생할 거니깐 코드 실행 중단하고 except 쪽으로 가서 코드를 실행함. 

 

특정 예외만 처리하기

a_list = [50, 40, 30, 20, 10]

try:
    index = int(input("리스트의 인덱스를 입력하세요 >>> "))
    value = int(input("해당 원소의 나눌 값을 입력하세요"))
    result = a_list[index] / value
    print("result =", result)

except ZeroDivisionError: #except ZeroDivisionError as e
    print("숫자를 0으로 나눌 순 없습니다.")

except IndexError: #except IndexError as e
    print("잘못된 인덱스입니다.")

 

6. else

7. finaly

try:
	실행할 코드
    
except:
	예외가 발생했을 때 처리하는 코드
    
else:
	예외가 발생하지 않았을 때 실행할 코드
    
finally:
	예외 발생 여부와 상관없이 항상 실행할 코드

else는 except 바로 다음에 와야 하며 except를 생략할 수는 없음.

finally는 except와 else를 생략할 수 있음.

try는 함수가 아니므로 지역변수와 무관함.

따라서 try 안에서 변수를 만들더라도 try 바깥에서 사용가능.

 

else 사용 예시

num_list = [23,145,1551,2451,5121]

try:
    index = int(input("리스트의 인덱스를 입력하시오 >>> "))
    value = int(input("해당 원소의 나눌 값을 입력하세요. >>> "))
    result = num_list[index] / value

except Exception as e:
    print("예외가 발생하였습니다.", e)

else:
    print("result =", result)

 

finally 사용 예시

num_list = [100,90,80,70,60]

try:
    index = int(input("리스트의 인덱스를 입력하세요 >>> "))
    value = int(input("해당 원소의 나눌 값을 입력하세요 >>> "))
    result = num_list[index] / value

except Exception as e:
    print("예외 발생:", e)

else:
    print("result =",result)

finally:
    print("코드의 수행이 종료되었습니다.")

 

 

8. raise

사용자가 정의한 예외 발생시키기

try:
    even_number = int(input("짝수를 입력하세요 >>> "))
    if even_number % 2 == 0: # 짝수가 아니면 예외 발생
        print(f"{even_number}는 짝수 입니다.")
    else:
        raise Exception("짝수가 아닙니다.")
        
except Exception as e:
    print("예외가 발생하였습니다.", e)

 

raise의 처리과정

def is_even_number():
	even_number = int(input("짝수를 입력하세요 >>> "))
    if even_number % 2 == 0:
    	print(f"{even_number}는 짝수입니다.")
    
    else:
    	raise Exception("짝수가 아닙니다.")
        

try:
	is_even_number()
    
except Exception as e:
	print("예외가 발생하였습니다", e)

is_even_number 함수는 안에 try except이 없는 상태에서 raise로 예외를 발생시켰다.

이렇게 되면 함수 바깥에 있는 except에서 예외가 처리된다.

 

예외가 발생하더라도 현재 코드 블록에서 처리해줄 except가 없다면

except가 나올 때까지 계속 상위 코드 블록으로 올라간다.

 

만약 함수 바깥에도 처리해 줄 except가 없다면 코드 실행은 중지되고 에러가 표시됨. 

 

예외 다시 발생시키기

def is_even_number():
    try: 
        even_number = int(input("짝수를 입력하세요 >>> "))
        if even_number % 2 == 0: # 짝수가 아니면 예외 발생
            print(f"{even_number}는 짝수 입니다.")
        else:
            raise Exception("짝수가 아닙니다.")
            
    except Exception as e:
        print("is_even_number() 함수에서 예외가 발생하였습니다.", e)
        raise # raise로 현재 예외를 다시 발생시켜 상위 코드 블럭으로 넘김
    
try:
    is_even_number()
    
except Exception as e:
    print("하위 코드 블럭에서 예외가 발생하였습니다.", e)
def is_even_number():
    try: 
        even_number = int(input("짝수를 입력하세요 >>> "))
        if even_number % 2 == 0: # 짝수가 아니면 예외 발생
            print(f"{even_number}는 짝수 입니다.")
        else:
            raise Exception("짝수가 아닙니다.")
            
    except Exception as e:
        print("예외가 발생하였습니다.", e)
        raise RuntimeError("is_even_number 함수에서 예외가 발생하였습니다.")
    
try:
    is_even_number()
    
except RuntimeError as e:
    print("하위 코드 블럭에서 예외가 발생하였습니다.", e)

 

9. assert

assert 조건식
assert 조건식, 에러메시지

assert는 지정된 조건식이 거짓일 때 AssertionError 예외를 발생시키며 

조건식이 참이면 그냥 넘어갑니다.

 

try:
	even_number = int(input("짝수 입력: "))
    assert even_number % 2 == 0 
    
except Exception as e:
	print("예외가 발생하였습니다.")

 

 

+ 참고

jupyter 창에서는

!pip install pyfiglet

 

터미널에서

pip install pyfiglet

pip show pyfiglet

 

ctrl_c 로 중단

 

jupyter 에서는 clear라는 명령 불가

 

일반적으로 함수에 이렇게 매개변수를 지정해서 

함수를 호출할 때 매개변수 칸에 자신이 원하는 숫자를 넣으면 결과가 바르게 나온다.

def func_01(x, y, z = 0):
	return x + y + z
    
s = func_01(10,20)
print(s)

 

그런데 매개변수를 정해놓지 않는 방법이 있는데 이건

가변 인수(Arbitrary Argument)방식이라고 한다.

이건 예를 들어, 리스트, 딕셔너리, 세트 등을 매개변수로 사용할 경우 전달 개수를 미리 알 수 없을 경우 자주 사용한다.

def func_01(*args): 
	print(args)
    return sum(args[0])
    
result = func_01([x for x in range(1,11)]) # list argument
print(f"func_01 함수 호출 결과: {s}")

이런 식으로 쓸 수 있는데 

그런데 여기서 한 가지 잘못된 점이 있다. 이걸 출력하면 원소가 리스트인 튜플로 출력이 되는데 이렇게 말고

그냥 튜플로 나오게 하기 위해서는 

def func_01(*args): 
	print(args)
    return sum(args)
    
result = func_01(*[x for x in range(1,11)]) # list argument
print(f"func_01 함수 호출 결과: {s}")

이런식으로 함수를 호출할 때 함수의 괄호 안 매개변수가 되는 리스트나 튜플 앞에 *을 붙여주면 된다.

 

튜플이 아닌 딕셔너리 형태로 전달하기 위해서는 함수의 파라미터 앞에 **을 써주면 된다.

def func_01(**kwargs):
	print(kwargs)
    
func_01(name = "Tom Crise", born = "Syracuse, New York, U.S", age =58)
func_01(my_car = "Pony", type = "used car")

a_dict = {"my_car": "Pony", "type": "used car"}
func_01(**a_dict)

 

함수도 역시 객체가 가능하며, 파라미터로 넘겨주는 게 가능하다.

def hello():
	print("안녕하세요")
    
def say(foo):
	foo()

say(hello)

함수가 객체가 가능하니 당연하게도 리스트 또는 튜플 원소로 함수명 사용이 가능하다.

def plus(x, y):
	return x+y
    
def minus(x,y):
	return x-y
    
f1 = (plus, minus) # tuple
f2 = [plus, minus] # list

print(f1, f2)

'프로그래밍 > Python' 카테고리의 다른 글

Python - 재귀함수  (0) 2023.10.14
Python - 모듈, 예외처리  (1) 2023.10.14
Python - Lambda함수  (0) 2023.10.08
Python 문제 - 학생들 점수 합 및 평균 구하기  (0) 2023.10.08
Python 문자열 정렬, set  (0) 2023.10.08

lambda는 함수를 생성할 때 사용하는 def와 동일한 역할

add = lambda a, b : a+b
result = add(10, 20)
print(result)


def add(a,b):
	return a+b
    
result = add(10, 20)
print(result)

# 모두 같은 결과가 나옴.

 

lambda 사용

items = [
    ("food1", 100),
    ("food2", 90),
    ("food3", 70)
]

# 익명 함수로 item list 내 3개 튜플 쌍 원소 중 두 번째(숫자) 원소로 정렬하는 방법
items.sort(key = lambda item: item[1], reverse = True) 
print(items)

# Map
scores = list(map(lambda item: item[1], items)) # [100, 90, 70]만 추출 
# items 안에 있는 튜플 값을 가져와서 값을 확인할건데 그 튜플 안의 두 번째 값을 item을 가져옴. 그거 한 데 묶어서 리스트화 시켜서 출력
print(scores)

# filter에 lambda 함수 적용하여 값이 80이상만 추출하는 방법
high_scores = list(filter(lambda item: item[1] >= 80, items))
print(high_scores)

간단하게 푼 코드

scores = \
    [[80, 80, 81],
     [84, 92, 63],
     [63, 73, 97],
     [69, 93, 85],
     [83, 84, 93]]

for student_num, ave in enumerate(scores):
    print(f"{student_num + 1} : {round(sum(ave)/len(ave))}")

 

 

더 복잡하게 푼 코드

print("[국, 영, 수]")
print("-"*32)

for row in range(len(scores)):
    s = 0
    for column in range(len(scores[row])):
        s += scores[row][column]
    print(f"{scores[row]}  합: {s}  평균: {round(s/len(scores[row]), 2)}")

 

'프로그래밍 > Python' 카테고리의 다른 글

Python - 개수 지정 없이 매개변수 전달  (0) 2023.10.13
Python - Lambda함수  (0) 2023.10.08
Python 문자열 정렬, set  (0) 2023.10.08
Python zip, enumerate 함수 사용  (2) 2023.10.08
Python 비트 연산자 정리  (0) 2023.10.07

+ Recent posts