Q1. Zlotkey와 동일한 부서에 속한 모든 사원의 이름과 입사일을 표시하는 질의를 작성하십시오. Zlotkey는 제외.

select e1.last_name, e1.hire_date
from employees e1 join employees e2
on e2.department_id = (select e1.department_id
from employees e1
    where e1.last_name = 'Zlotkey')
and e1.last_name <> e2.last_name;
#sol2
select last_name, hire_date
from employees
where department_id = (select department_id
from employees
    where last_name = 'Ziotkey');
    




Q2. 급여가 평균 급여보다 많은 모든 사원의 사원번호와 이름을 표시하는 질의를 작성하고 결과를 급여에 대해 오름차순으로 정렬하십시오.

select employee_id, last_name, salary
from employees
where salary > (select avg(salary)
from employees)
order by salary;


Q3. 이름에 u가 포함된 사원과 같은 부서에서 일하는 모든 사원의 사원 번호와 이름을 표시하는 질의를 작성하시오.

select employee_id, last_name
from employees
where department_id = (select distinct department_id
from employees 
where last_name like '%u%');



Q4. 부서 위치 ID가 1700인 모든 사원의 이름, 부서 번호 및 업무 ID를 표시하십시오.

select last_name, department_id, job_id
from employees join locations
where location_id = 1700; 
#sol2
select last_name, department_id, job_id
from employees 
where department_id in (select deprtment_id
from departments 
    where location_id = 1700);


 
Q5. King에게 보고하는 모든 사원의 이름과 급여를 표시하십시오.

select last_name, salary
from employees
where manager_id in (select employee_id   #출력하는 값이 단일행이 아니라서 = 만 쓰면 안됌
from employees 
where last_name = 'king'); 

   

#sol2.
select last_name, salary
from employees
where manager_id = any (select employee_id 
from employees 
where last_name = 'king');



Q6. Executive 부서의 모든 사원에 대한 부서 번호, 이름 및 업무 ID를 표시하십시오.

select e.department_id, e.last_name, e.job_id
from employees e join departments d
where e.department_id = d.department_id
and d.department_name = 'executive';
#sol2
select department_id, last_name, job_id
from employees
where department_id = (select department_id 
from departments 
where department_name = 'Executive');




Q7. 3번 문제의 질의를 수정하여 평균 급여보다 많은 급여를 받고 이름에 u가 포함된 사원과 같은 부서에서 근무하는 모든 사원의 사원번호, 이름 및 급여를 표시하시오.

select employee_id, last_name, salary
from employees
where salary > all(select avg(salary)
from employees)
and department_id in (select department_id
from employees 
where last_name like '%u%');


    

'MySQL은 좀 낫다면서요' 카테고리의 다른 글

MySQL #테이블 : 게시판만들기  (0) 2021.06.17
MySQL #테이블  (0) 2021.06.17
MySQL #함수  (0) 2021.06.17
MySQL #Ch5.함수 : 연습문제  (0) 2021.06.17
MySQL #CH4. Join : 연습문제  (0) 2021.06.16

#if함수 #if(수식, 참일때실행문, 거짓일때실행문)

select if(hire_date like '2005%', last_name, '2005년 입사 아님')

from employees;

 

 

#ifnull(컬럼/값, 널일때실행문)

select last_name, commission_pct, 12*salary+12*salary*commission_pct

from employees;
select last_name, commission_pct, 12*salary+12*salary*ifnull(commission_pct, 0)

from employees;

 

 

#nullif(exp1, exp2): exp1과 exp2가 같으면 null, 같지 않으면 exp1 반환

select last_name, length(last_name), first_name, length(first_name), 
	nullif(length(last_name), length(first_name))

from employees;

 

 

#case문: 비교할 조건이 여러개 일때 사용

case exp when 값1 then 실행문
	when 값2 then 실행문
	when 값3 then 실행문
	else 실행문
end as '컬럼별칭' 
select department_id,
case department_id when 10 then '10번 부서'
	when 20 then '20번 부서' when 30 then '30번 부서'
	else '이외 부서' end as '부서명'
from employees;

'MySQL은 좀 낫다면서요' 카테고리의 다른 글

MySQL #테이블  (0) 2021.06.17
MySQL #Ch6.서브쿼리 : 연습문제  (0) 2021.06.17
MySQL #Ch5.함수 : 연습문제  (0) 2021.06.17
MySQL #CH4. Join : 연습문제  (0) 2021.06.16
MySQL #조인(Join)  (0) 2021.06.16

Q1. 그룹 함수는 여러 행에 적용되어 그룹 당 하나의 결과를 출력합니다. ( True / False ) T

 

Q2. 그룹 함수는 계산에 널을 포함합니다. ( True / False ) F

 

Q3. WHERE 절은 그룹 계산에 행을 포함시키기 전에 행을 제한합니다. ( True / False ) T

 

Q4. 모든 사원의 급여 최고액, 최저액, 총액 및 평균액을 표시하십시오. 열 레이블을 각각 Maximum, Minimum, Sum 및 Average 로 지정하고 결과를 정수로 반올림한 후 작성한 SQL문을 lab5_4.sql이라는 파일에 저장하십시오.

 

select max(salary) as Maximum, min(salary) as Minimum, sum(salary) as Sum, 
round(avg(salary), 1) as Average
from employees;

 



Q5. lab5_4.sql의 질의를 수정하여 각 업무 유형별로 급여 최고액, 최저액, 총액 및 평균액을 표시하십시오. lab5_4.sql을 lab5_5.sql로 다시 저장하고 lab5_5.sql의 명령문을 실행하십시오.

select job_id, max(salary) as Maximum, min(salary) as Minimum, sum(salary) as Sum, 
avg(salary) as Average
from employees
group by job_id;

 

 


Q6. 업무가 동일한 사원 수를 표시하는 질의를 작성하십시오.

select job_id, count(job_id) as 'Count(*)'
from employees
group by job_id;

 



Q7. 관리자는 나열하지 말고 관리자 수를 확인하십시오. 열 레이블은 Number of Managers로 지정하십시오 .힌트 : MANAGER_ID 열을 사용하여 관리자 수를 확인하십시오.

select count(manager_id) as 'Number of Managers'
from employees;

 



Q8. 최고 급여와 최저 급여의 차액을 표시하는 질의를 작성하고 열 레이블을 DIFFERENCE로 지정하십시오.

select max(salary) - min(salary) as 'DIFFERENCE'
from employees

 

 


Q9. 관리자 번호 및 해당 관리자에 속한 사원의 최저 급여를 표시하십시오. 관리자를 알 수 없는 사원 및 최저 급여가 $ 6,000 미만인 그룹은 제외시키고 결과를 급여에 대한 내림차순으로 정렬하십시오.

select manager_id, min(salary) 
from employees    
WHERE manager_id IS NOT NULL      
GROUP BY manager_id      
HAVING MIN(salary) > 6000      
ORDER BY MIN(salary) DESC;

 



Q10. 각 부서에 대해 부서 이름, 위치, 사원 수, 부서 내 모든 사원의 평균 급여를 표시하는 질의를 작성하고, 열 레이블을 각각 Name, Location, Number of People 및 Salary로 지정하십시오. 평균 급여는 소수점 둘째 자리로 반올림하십시오.

select department_name as 'Name', location_id as 'Location', count(*) as 'Number of People', 
round(avg(salary), 1) as Salary 
from employees join departments
using(department_id)
group by department_name;

 



Q11. 총 사원 수 및 2005, 2006, 2007, 2008년에 입사한 사원 수를 표시하는 질의를 작성하고 적합한 열 머리글을 작성하십시오.

select count(*) TOTAL,
sum(if(hire_date like '2005%', 1, 0)) '2005%',
sum(if(hire_date like '2006%', 1, 0)) '2006%',
sum(if(hire_date like '2007%', 1, 0)) '2007%',
sum(if(hire_date like '2008%', 1, 0)) '2008%'
from employees;

 


Q12. 업무를 표시한 다음 해당 업무에 대해 부서 번호별 급여 및 부서 20, 50, 80 및 90의 급여 총액을 각각 표시하는 행렬 질의를 작성하고 각 열에 적합한 머리글을 지정하십시오.

select job_id,
sum(case department_id when 20 then salary end) Dept20,
sum(case department_id when 50 then salary end) Dept50,
sum(case department_id when 80 then salary end) Dept80,
sum(case department_id when 90 then salary end) Dept90,
sum(salary) Total
from employees
group by job_id;

'MySQL은 좀 낫다면서요' 카테고리의 다른 글

MySQL #Ch6.서브쿼리 : 연습문제  (0) 2021.06.17
MySQL #함수  (0) 2021.06.17
MySQL #CH4. Join : 연습문제  (0) 2021.06.16
MySQL #조인(Join)  (0) 2021.06.16
MySQL #CH2. Select : 연습문제  (0) 2021.06.15


Q1. 모든 사원의 이름, 부서 번호, 부서 이름을 표시하는 질의를 작성하십시오.

select e.last_name, e.department_id, d.department_name
from employees e, departments d
where e.department_id = d.department_id;
#sol2.
select last_name, e.department_id, department_name
from employees e join departments d
on e.department_id = d.department_id;



Q2. 부서 80에 속하는 모든 업무의 고유 목록을 작성하고 출력 결과에 부서의 위치를 포함시키십시오.

select e.job_id, d.location_id
from employees e, departments d
where e.department_id = d.department_id
and d.department_id =80;
#sol2.
select job_id, location_id
from employees join departments
using(department_id)
where department_id = 80;


Q3. 커미션을 받는 사원의 이름, 부서 이름, 위치 ID 및 도시를 표시하는 질의를 작성하십시오.

#city가 있는 테이블이 뭔지 못찾았음.
select e.last_name, e.department_id, d.location_id
from employees e, departments d
where e.department_id = d.department_id
and commission_pct is not null; 
#sol2
select last_name, department_name, location_id, city
from employees natural join departments
natural join locations
where commission_pct is not null;


Q4. 이름에 a(소문자)가 포함된 모든 사원의 이름과 부서 이름을 표시하시오.

select e.last_name, e.department_id
from employees e, departments d
where e.department_id = d.department_id
and last_name like '%a%';
#sol2.
select last_name, department_id
from employees join departments
using(department_id)
where last_name like '%a%'
and not last_name like 'a%';



Q5. Toronto에서 근무하는 모든 사원의 이름, 업무, 부서 번호 및 부서 이름을 표시하는 질의를 작성하십시오.

select last_name, job_id, department_id, department_name 
from employees join departments
using(department_id)
join locations
using(location_id)
where city = 'toronto';


Q6. 사원의 이름 및 사원 번호를 관리자의 이름 및 관리자 번호화 함께 표시하고 각각의 열 레이블을 Employee, Emp#, Manager, Mgr#로 지정하십시오.

select e.last_name as 'Employee', e.employee_id as 'EMP#', 
m.last_name as 'Manager', m.employee_id as 'Mgr#'
from employees e join employees m
on e.manager_id = m.employee_id;


Q7. 6번을 수정하되 King을 포함하여 관리자가 없는 모든 사원을 표시하도록 하고 결과를 사원 번호를 기준으로 정렬하십시오.

select e.last_name as 'Employee', e.employee_id as 'EMP#', 
m.last_name as 'Manager', m.employee_id as 'Mgr#'
from employees e left outer join employees m
on e.manager_id = m.employee_id;



Q8. 지정한 사원의 이름, 부서 번호 및 지정한 사원과 동일한 부서에서 근무하는 모든 사원을 표시하도록 질의를 작성하고 각 열에 적합한 레이블을 지정하십시오.

select e.last_name, e.department_id, c.last_name as colleague
from employees e join employees c
on e.department_id = c.department_id
where e.last_name <> c.last_name;


Q9. JOB_GRADES 테이블의 구조를 표시하고 모든 사원의 이름, 업무, 부서 이름, 급여 및 등급을 표시하는 질의를 작성하십시오.

# Job_grade 테이블
create table job_grades(
gra char(1) primary key,
lowest_sal int ,
highest_sal int
);

insert into job_grades values('A', 1000, 2999);
insert into job_grades values('B', 3000, 5999);
insert into job_grades values('C', 6000, 9999);
insert into job_grades values('D', 10000, 14999);
insert into job_grades values('E', 15000, 24999);
insert into job_grades values('F', 25000, 40000);
desc job_grades;

select * from job_grades;
desc job_grades;
select last_name, job_id, department_name, salary, gra
from employees join departments
using (department_id)
join job_grades
on salary between lowest_sal and highest_sal;


Q10. Davies라는 사원보다 늦게 입사한 사원의 이름과 입사일을 표시하는 질의를 작성하십시오.

select e2.last_name, e2.hire_date
from employees e1 join employees e2
on e1.hire_date < e2.hire_date
where e1.last_name = 'Davies';


Q11. 관리자보다 먼저 입사한 모든 사원의 이름 및 입사일을 관리자의 이름 및 입사일과 함께 표시하고 열 레이블을 각각 Employee, Emp Hired, Manager, Mgr Hired

select e.last_name as 'Employee', e.hire_date as 'Emp Hired', 
m.last_name as 'Manager', m.hire_date as 'Mgr Hired'
from employees e join employees m
on e.hire_date < m.hire_date;

'MySQL은 좀 낫다면서요' 카테고리의 다른 글

MySQL #Ch6.서브쿼리 : 연습문제  (0) 2021.06.17
MySQL #함수  (0) 2021.06.17
MySQL #Ch5.함수 : 연습문제  (0) 2021.06.17
MySQL #조인(Join)  (0) 2021.06.16
MySQL #CH2. Select : 연습문제  (0) 2021.06.15

 

조인(Join)
  • 등가조인

    : 조인기준 컬럼의 값이 같을 조건으로조인

 

select 이름, 부서이름

from 사원테이블 natural join 부서테이블

 

select 이름, 부서이름

from 사원테이블 join 부서테이블

using(부서번호)   -> 조인할 컬럼을 지정

 

select 이름,부서이름

from 사원테이블 e join 부서테이블 d

on e.부서번호 = d.부서번호

where 부서번호 = 10

 

 

 

  • Outer Join(포괄조인)

     조인 조건을 만족하지 않는 행을 같이 보여줌

     Left outer join : 왼쪽 테이블의 만족하지 않는 행을 같이 보여줘라

#left join
select 이름,부서이름

from 사원테이블 e left outer join 부서테이블 d

on e.부서번호 = d.부서번호

     

     Right outer join : 오른쪽 테이블의 만족하지 않는 행을 같이 보여줘라

#right join

select 이름,부서이름

from 사원테이블 e right outer join 부서테이블 d

on e.부서번호 = d.부서번호

 

     full join (sql에서는 제공 안해서 합집합으로)

#full outer join
select 이름,부서이름

from 사원테이블 e left outer join 부서테이블 d

on e.부서번호 = d.부서번호

union

select 이름,부서이름

from 사원테이블 e right outer join 부서테이블 d

on e.부서번호 = d.부서번호

 

  • self join

     자기 자신을 조인 -> 테이블 별칭 꼭 사용해야 함

     ex) 사번이 175번인 사람의 매니저 이름이 무엇인가?

select e.이름, m.이름
from 사원테이블 e join 사원테이블 m
on e.manager_id = m.사번
where e.사번= 175

 

  • 비등가조인

     : 등가(=)가 아닌 조건으로 조인

create table job_grades(
gra char(1) primary key,
lowest_sal int ,
highest_sal int
);

insert into job_grades values('A', 1000, 2999);
insert into job_grades values('B', 3000, 5999);
insert into job_grades values('C', 6000, 9999);
insert into job_grades values('D', 10000, 14999);
insert into job_grades values('E', 15000, 24999);
insert into job_grades values('F', 25000, 40000);
desc job_grades;

select * from job_grades;
select employee_id, last_name, salary, gra
from employees e join job_grades j
on e.salary between j.lowest_sal and j.highest_sal;

'MySQL은 좀 낫다면서요' 카테고리의 다른 글

MySQL #Ch6.서브쿼리 : 연습문제  (0) 2021.06.17
MySQL #함수  (0) 2021.06.17
MySQL #Ch5.함수 : 연습문제  (0) 2021.06.17
MySQL #CH4. Join : 연습문제  (0) 2021.06.16
MySQL #CH2. Select : 연습문제  (0) 2021.06.15

Q1. 급여가 $12,000를 넘는 사원의 이름과 급여를 표시하는 질의를 작성하시오.

select last_name, salary 
from employees
where salary >=12000 ;


Q2. 사원번호가 149인 사원의 이름과 부서 번호를 표시하는 질의를 작성하시오.

select last_name, department_id 
from employees
where employee_id = 149;



Q3. 급여가 $5,000에서 $12,000 사이에 포함되지 않는 모든 사원의 이름과 급여를 표시하는 질의를 작성하시오.

select last_name, salary 
from employees
where salary 
not in (5000<=salary, salary<=12000) ;


Q4. 2005년 2월 20일과 2005년 5월 1일 사이에 입사한 사원의 이름, 업무 ID 및 시작일을 표시하되, 시작일을 기준으로 오름차순으로 정렬하시오.

select last_name, job_id, hire_date
from employees
where hire_date between 20050220 and 20050501
order by hire_date asc;
#sol2
select last_name, job_id, hire_date
from employees
where hire_date between date('2000-02-20') and date('2000-05-01')
order by hire_date;



Q5. 부서 20 및 50에 속하는 모든 사원의 이름과 부서 번호를 이름을 기준으로 영문자순으로 표시하십시오.

select last_name, department_id
from employees
where department_id between 20 and 50
order by last_name;


Q6. 급여가 $5,000와 $12,000 사이이고 부서 번호가 20 또는 50인 사원의 이름과 급여를 나열하도록 [3번 문제]을 수정 하고, 열 레이블을 Employee와 Monthly Salary로 각각 지정하여 실행하시오.

select last_name as Employee, salary as 'Monthly Salary'
from employees
where salary between 5000 and 12000
and (department_id =20 or department_id=50);
#sol2
select last_name as Employee, salary as 'Monthly Salary'
from employees
where salary between 5000 and 12000
and department_id in (20 ,50);

 


Q7. 2004년에 입사한 모든 사원의 이름과 입사일을 표시하시오.

select last_name, hire_date
from employees
where hire_date like '__04%';


Q8. 관리자가 없는 모든 사원의 이름과 업무를 표시하시오.

select last_name, job_id
from employees
where manager_id is null;

 

Q9. 커미션을 받는 모든사원의 이름, 급여 및 커미션을 급여 및 커미션을 기준으로 내림차순으로 정렬하여 표시하시오.

select last_name, salary, commission_pct
from employees
where commission_pct is not null
order by commission_pct desc;


Q10. 이름의 세번째 문자가 a인 모든 사원의 이름을 표시하십시오.

select last_name
from employees
where last_name like '__a%';


Q11. 이름에 a와 e가 있는 모든사원의 이름을 표시하십시오.

select last_name
from employees
where last_name like '%a%e%' or '%e%a%';


Q12. 업무가 영업 사원 또는 사무원이면서 급여가 $2,500, $3,500 또는 $7,000가 아닌 모든 사원의 이름, 업무 및 급여를 표시하십시오.

select last_name, job_id, salary
from employees
where job_id = 'SA_REP' or job_id = 'ST_CLERK'
and salary not in (2500, 3000, 7000);


Q13. 커미션 비율이 20%인 모든 사원의 이름, 급여 및 커미션을 표시하도록 [6번 문제]을 수정하십시오

select last_name as Employee, salary as 'Monthly Salary', commission_pct
from employees
where commission_pct = 0.20

 

 

'MySQL은 좀 낫다면서요' 카테고리의 다른 글

MySQL #Ch6.서브쿼리 : 연습문제  (0) 2021.06.17
MySQL #함수  (0) 2021.06.17
MySQL #Ch5.함수 : 연습문제  (0) 2021.06.17
MySQL #CH4. Join : 연습문제  (0) 2021.06.16
MySQL #조인(Join)  (0) 2021.06.16

 

접근제어 Private

 

접근제어는 클래스의 멤버변수나 메소드를 외부 접근을 허용할지 여부를 지정해준다.
객체지향 기반 프로그래밍에서는 접근 제어자 즉, private, protected, public을 이용한 정보 은닉을 통해 외부로부터 데이터를 보호한다. 이를 통해 객체의 속성과 메소드를 하나로 묶고, 실제 구현 내용의 일부는 외부에 감추어 은닉할 수 있는 캡슐화가 가능한다.

일반 멤버 변수나 메소드는 클래스 밖에서도 사용가능한데 이런 것들이 public이고, 클래스 밖에서는 사용이 불가능하게 하는 것이 private이다.

private 접근제어자는 이름앞에 __를 붙여서 사용한다.

 

class Test:
    def __init__(self):
        self.__a = 10
        self.b = 20

    def setData(self,a, b):
        self.__a = a
        self.b = b

    def printData(self):
        print('a:', self.__a)
        print('b:', self.b)

def main():
    t1 = Test()
    t1.printData()
    t1.setData(3,4)
    t1.printData()

    t1.b = 200

    print('t1.a:', t1.__a)
    print('t2.b:', t1.b)

main()

private 멤버 때문에 에러가 났다. 

 

 

class Test:
    def __init__(self):
        self.__a = 10
        self.b = 20

    def setData(self,a, b):
        self.__a = a
        self.b = b

    def printData(self):
        print('a:', self.__a)
        print('b:', self.b)

    def setA(self, a):  #setter: 클래스 밖에서 private 멤버에 값을 설정하는 메소드
       self.__a = a

    def getA(self):  #getter:클래스 밖으로 private 멤버 값을 반환하여 외부에서도 읽을 수 있게 하는 메소드
        return self.__a

def main():
    t1 = Test()
    t1.printData()
    t1.setData(3,4)
    t1.printData()

    t1.setA(100)
    t1.b = 200

    print('t1.a:', t1.getA())
    print('t2.b:', t1.b)

main()

짜잔. 이제는 a가 보이지롱.

setter와 getter을 이용하여 프라이빗한 a를 찾아내고 받아와서 메소드에 적용시켜주면 숨어있던 변수들도 꺼내 쓸 수 있다.

 

 

예제2)

class Member:
    def __init__(self, id='', pwd='', email=''):
        self.__id = id
        self.__pwd = pwd
        self.__email = email

    def __str__(self):   #객체를 설명하는 메소드
        return 'id:'+self.__id+'/ pwd:'+self.__pwd+'/ email:'+self.__email

    def setA(self, id):
        self.__id = id

    def getA(self):
        return self.__id


def main():
    m1 = Member('aaa', '111', 'aaa@email.com')
    m2 = Member('bbb', '222', 'bbb@email.com')
    m3 = Member('ccc', '333', 'ccc@email.com')
    print(m1)
    print(m2)
    print(m3)


    m1.setA('aaa1')
    m2.setA('bbb2')
    m3.setA('ccc3')
    print(m1)
    print(m2)
    print(m3)

main()

 

class PocketMon():  #상속이 목적. 객체생성 안함
    def __init__(self):
        self.name = ''
        self.hp = 0
        self.exp = 0
        self.lv = 1

    #상속하기 위한 메서드. 간단한 출력문만 작성. 실제 동작은 각 캐릭터의 하위 클래스에서
    def 밥먹기(self):
        print(self.name, '이(가) 밥을 먹는다.')

    def 잠자기(self):
        print(self.name, '이(가) 잠을 잔다.')

    def 운동하기(self):
        print(self.name, '이(가) 운동한다.')

    def 놀기(self):
        print(self.name, '이(가) 논다.')

    def 레벨체크(self):
        print(self.name, '레벨체크')

    #모든 캐릭터가 동일하게 동작하므로 부모 클래스에 구현한 것을 하위에서 그대로 사용
    def 상태정보(self):
        print(self.name, '상태정보 출력')
        print('HP:', self.hp)
        print('EXP:', self.exp)
        print('LV:', self.lv)


class 피카츄(PocketMon):
    def __init__(self):
        super().__init__()
        self.name = '피카츄'
        self.hp = 30   #캐릭터의 초기값 할당

    def 밥먹기(self):
        super().밥먹기()  #부모 클래스의 밥먹기()호출
        self.hp += 5

    def 잠자기(self):
        super().잠자기()
        self.hp += 10

    def 운동하기(self):
        super().운동하기()
        self.hp -= 10
        flag = self.hp>0   #살았나 죽었나 확인한 값 flag에 저장
        if flag:
            self.exp += 8
            self.레벨체크()
        return flag

    def 놀기(self):
        super().놀기()
        self.hp -= 5
        flag = self.hp > 0
        if flag:
            self.exp += 3
            self.레벨체크()
        return flag

    def 레벨체크(self):
        if self.exp>=20:
            self.lv += 1
            print(self.name, '레벨업!')
            self. exp -= 20

    def 전기공격(self):
        print('피카츄 백만볼트~~~~~! 피카피카!!!')

class 꼬부기(PocketMon):
    def __init__(self):
        super().__init__()
        self.name = '꼬부기'
        self.hp = 40

    def 밥먹기(self):
        super().밥먹기()
        self.hp += 7

    def 잠자기(self):
        super().잠자기()
        self.hp += 12

    def 운동하기(self):
        super().운동하기()
        self.hp -= 15
        flag = self.hp>0
        if flag:
            self.exp += 10
            self.레벨체크()
        return flag

    def 놀기(self):
        super().놀기()
        self.hp -= 8
        flag = self.hp > 0
        if flag:
            self.exp += 3
            self.레벨체크()
        return flag

    def 레벨체크(self):
        if self.exp>=25:
            self.lv += 1
            print(self.name, '레벨업!')
            self. exp -= 25

    def 물대포(self):
        print('물대포 공격!! 꼬북~~!!!!')


class 파이리(PocketMon):
    def __init__(self):
        super().__init__()
        self.name = '파이리'
        self.hp = 60

    def 밥먹기(self):
        super().밥먹기()
        self.hp += 12

    def 잠자기(self):
        super().잠자기()
        self.hp += 22

    def 운동하기(self):
        super().운동하기()
        self.hp -= 20
        flag = self.hp>0
        if flag:
            self.exp += 15
            self.레벨체크()
        return flag

    def 놀기(self):
        super().놀기()
        self.hp -= 10
        flag = self.hp > 0
        if flag:
            self.exp += 7
            self.레벨체크()
        return flag

    def 레벨체크(self):
        if self.exp>=30:
            self.lv += 1
            print(self.name, '레벨업!')
            self. exp -= 30

    def 불대포(self):
        print('파이리 불대포 공격!! (하지만 파이리는 말을 듣지 않았다.)')

class Menu:
    def __init__(self, mon):
        self.mon = mon

    def run(self):
        flag = True
        while flag:
            menu = int(input('1.밥먹기 2.잠자기 3.운동하기 4.놀기 5.상태확인 6.특기공격 7.종료'))
            if menu == 1:
                self.mon.밥먹기()
            elif menu == 2:
                self.mon.잠자기()
            elif menu == 3:
                flag = self.mon.운동하기()
            elif menu == 4:
                flag = self.mon.놀기()
            elif menu == 5:
                self.mon.상태정보()
            elif menu == 6: #isinstance(obj, class name) obj 객체가 class name으로 만들어진 객체냐?(T/F)
                if isinstance(self.mon, 피카츄):   #서로 일치하지 않는 메소드를 이용하고 싶을 때
                    self.mon.전기공격()
                elif isinstance(self.mon, 꼬부기):
                    self.mon.물대포()
                elif isinstance(self.mon, 파이리):
                    self.mon.불대포()

            elif menu == 7:
                flag = False

        if menu == '4' or menu == '3':
            print('캐릭터 사망')

        print('게임종료')

def main():
    print('포켓몬 게임 시작')
    m = input('캐릭터 선택\n1.피카츄(기본) 2.꼬부기 3.파이리')
    mon = None
    if m == '1':
        mon = 피카츄()
    if m == '2':
        mon = 꼬부기()
    elif m == '3':
        mon = 파이리()

    mon.상태정보()
    mm = Menu(mon)
    mm.run()
main()

 

 

점점 class와 def를 쓰는 것이 익숙해지고 있다. 리스트나 for문을 써서 머리를 싸매는 것이 더 까탈스러움을 느낀다. 조만간 미니 팀프로젝트가 시작되는데 처음에는 무지 상태에서 프로젝트를 시작하는 것이 두려웠으나 가능성이 살짝 보인다. 한 5퍼 정도?

곧 DB가 시작되는데 괜찮겠지..?

상속(inheritance)

 

상속이란? 말 그대로 유전이다. 물려줌과 물려받는 것.

부모 객체의 변수나 메소드를 물려주고 자식 객체가 물려받아 활용하는 것.

 

상속은 
1. 코드 재사용을 높이기 위해서
2. 다형성 구현을 위해

3. 조립(인터페이스)의 편리를 위해

사용하게 된다. 

 

class 부모클래스:
    ...내용...

class 자식클래스(부모클래스):
    ...내용...

도출된 객체 중 비슷한 객체들이 발견되면 공통된 코드를 추출하여 부모 클래스로 정의하면 자식 클래스들은 비슷한 클래스들을 상속받아서 정의하면 된다.

 

 

자식클래스들은 꼭

def Child(Parent)
	super().__inint__()

이라고 정의해야지만 상속을 받을 수 있다.

 

예제1)

class Parent:
    def __init__(self):
        self.a=10 #멤버변수=한개
        print('Parent 생성자')

    def method1(self):
        print('메서드1')

class Child(Parent): #패런트 클래스를 상속받은 차일드 클래스. 부모의 멤버변수와 메서드를 물려받는다.
    def __init__(self):
        super().__init__()    #super():부모객체 반환
        print('Child 생성자')
        self.b=20

    def method2(self):   #메소드 method1, method2 2개
        print('메소드2')

class Child2(Parent):
    def __init__(self):
        super().__init__()
        print('Child 생성자')
        self.c=20
        self.d=40

    def method3(self):   #메소드 method1, method2 2개
        print('메소드3')

def main():
    c1 = Child()
    print('c1.a: ', c1.a)
    print('c1.b: ', c1.b)

    c1.method1()
    c1.method2()


    c2 = Child2()
    print('c2.a: ', c2.a)
    print('c2.c: ', c2.c)
    print('c2.d: ', c2.d)

    c2.method1()
    c2.method3()

main()

 

 

 

예제2) 

class Person:   #번호,이름,정보출력은 모두 다 공통이라 부모클래스로
    def __init__(self):
        self.number = 0
        self.name = ''
        self.dept = ''

    def printInfo(self):
        print('number:', self.number)
        print('name:', self.name)
        print('dept:', self.dept)

class Student(Person):
    def __init__(self,number, name, dept):
        super().__init__()
        self.number=number
        self.name=name
        self.dept=dept
        self.type='학생'
        self.subj=[]

    def 수강신청(self,sub):
        self.subj.append(sub)

    def print수강과목(self):
        print('수강과목')
        for i in self.subj:
            print(i)

class Prof(Person):
    def __init__(self, number, name, dept):
        super().__init__()
        self.number = number
        self.name = name
        self.dept = dept
        self.type = '교수'
        self.담당과목 = []

    def 담당과목추가(self, sub):
        self.담당과목.append(sub)

    def print담당과목(self):
        print('수강과목')
        for i in self.담당과목:
            print(i)

class Staff(Person):
    def __init__(self, number, name, dept):
        super().__init__()
        self.number = number
        self.name = name
        self.dept = dept
        self.type = '교직원'
        self.job = ''

    def setJob(self, job):
        self.job = job

    def printJob(self):
        print('담당직무:', self.job)


def main():
    s1= Student(1, 'aaa','컴퓨터공학')
    s1.수강신청('전산학개론')
    s1.수강신청('컴퓨터비전')
    s1.printInfo()
    s1.print수강과목()

    p1=Prof(2, 'bbb', '전자공학')
    p1.담당과목추가('c언어')
    p1.담당과목추가('VHDL')
    p1.printInfo()
    p1.print담당과목()

    s2=Staff(3,'ccc','HR')
    s2.setJob('인재양성')
    s2.printInfo()
    s2.printJob()

main()

 

 

 

 

오버라이딩(Overriding)

 

오버라이딩이란 부모로부터 상속받은 메소드를 현재 클래스에 맞게 수정하여 사용하는 것이다. 즉, 메소드의 재정의이다.

#메소드 재정의: 부모로부터 상속받은 매소드를 현재 클래스에 맞게 수정하여 사용.

class Point2D:
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def printPoint(self):
        print('x:', self.x, 'y:', self.y,end='')


class Point3D(Point2D):
    def __init__(self,x,y,z):
        super().__init__(x,y)
        self.z = z

    def printPoint(self):  #메소드 재정의
        super().printPoint()   #super().메소드 : 재정의한 메소드의 옛버전을 사용하고 싶을 때
        print(' z:', self.z)


def main():
    p1 = Point2D(1,2)
    p1.printPoint()
    print()

    p2 = Point3D(4,5,6)
    p2.printPoint()


main()

 

 

 

다형성(Polymorphism)

그럼 위에서 상속은 다형성 구현을 위해 사용한다고 했는데 다형성이 뭘까?

다형성은 같은 모양의 코드가 다른 동작을 하는 것이다. 다형성은 여러 객체를 하나의 타입으로 관리가 가능하기때문에 코드를 짧게 작성하는데 유리하다. 위에서 다룬 오버라이딩도 다형성의 한 예이다.

class Car:
    def __init__(self):
        self.name = ''

    def horn(self):
        print('자동차 빵빵')

class 소방차(Car):
    def __init__(self):
        super().__init__()
        self.name = '소방차'

    def horn(self):
        print('불꺼~~~~~~')


class 구급차(Car):
    def __init__(self):
        super().__init__()
        self.name = '구급차'

    def horn(self):
        print('삐오삐오')


class 경찰차(Car):
    def __init__(self):
        super().__init__()
        self.name = '경찰차'

    def horn(self):
        print('잡어~~~~~~')

def main():
    obj = None
    print('자동차를 선택하시오')
    s = input('1.소방차 2.구급차 3.경찰차')
    if s=='1':
        obj = 소방차()
    elif s == '2':
        obj = 구급차()
    elif s == '3':
        obj = 경찰차()
    else:
        ojb = 소방차()

    print(obj.name)
    obj.horn()

main()

차의 종류만 다를 뿐, 이름을 출력하고 경적소리를 프린트하는 것이 다 공통인 메소드이기 때문에 객체마다 메소드를 쓰는 것보다 위처럼 다형성을 이용해 작성하면 매우 간단해진다.

Q. 제품 등록, 수정, 삭제 등 제품관리 프로그램을 만드시오. (단, 제품번호는 자동할당 받아야 됌)

제품정보에는 제품번호, 제품명, 가격, 수량

메뉴에는 1.등록 2.검색 3.수정 4.삭제 5.전체출력 6.종료

 

#VO

class Product:
    cnt = 0
    def __init__(self, name='', price=0, amount=0):
        Product.cnt += 1
        self.num = Product.cnt
        self.name = name
        self.price = price
        self.amount = amount

    def __str__(self):
        return '제품번호:' + str(self.num) + '/ 제품명:' + self.name + '/ 가격:' + str(self.price) + '/ 수량:' + str(self.amount)
        print()

#DAO
class ProdDao:
    def __init__(self):
        self.datas = []

    def insert(self, p):
        self.datas.append(p)

    def delete(self, p):
        self.datas.remove(p)

    def select(self, num):
        for i in self.datas:
            if i.num == num:
                return i

    def selectAll(self):
        return self.datas


#Service
class ProdService:
    def __init__(self):
        self.dao = ProdDao()

    def addProd(self):
        name = input('제품명:')
        price = input('가격:')
        amount = input('수량:')

        p = Product(name, price, amount)
        self.dao.insert(p)

    def printProd(self):
        num = int(input('검색할 제품번호를 입력하시오.'))
        p = self.dao.select(num)
        if p == None:
            print('제품을 찾을 수 없습니다.')
        else:
            print(p)

    def editProd(self):
        num = int(input('검색할 제품번호를 입력하시오.:'))
        pd = self.dao.select(num)
        if pd == None:
            print('제품을 찾을 수 없습니다.')
        else:
            pd.price=int(input('수정할 가격을 입력하시오.'))
            pd.amount=int(input('수정할 수량을 입력하시오.'))
            print('수정되었습니다.')

    def delProd(self):
        num = int(input('검색할 제품번호를 입력하시오.:'))
        pd = self.dao.select(num)
        if pd == None:
            print('제품을 찾을 수 없습니다.')
        else:
            self.dao.delete(pd)
            print('삭제되었습니다.')

    def printAll(self):
        datas = self.dao.selectAll()
        for i in datas:
            print(i)

class Menu:
    def __init__(self):
        self.service = ProdService()

    def run(self):
        while True:
            menu = int(input('1.등록 2.검색 3.수정 4.삭제 5.전체출력 6.종료'))
            if menu == 1:
                self.service.addProd()
            if menu == 2:
                self.service.printProd()
            if menu == 3:
                self.service.editProd()
            if menu == 4:
                self.service.delProd()
            if menu == 5:
                self.service.printAll()
            if menu == 6:
                break

def main():
    pd=Menu()
    pd.run()

main()

야호! 간단한 프로그램이지만 뭔가를 만들어 내는 것에 익숙해지고 있다.

맨 처음 오류는 변수 num이 int타입인데 서비스 클래스에서 printProd 메소드에서의 검색할 num을 그냥 str로 입력받아 오류가 났었다.

그리고 두번째는 Attributeerror: 'Product' object has no attribute 'printprod'가 떴었다.

처음에는 Product 클래스에서 출력메소드명을 print라고 했었는데 이게 printProd와 서로 같지 않아서 생긴 오류였다.

서로 다른 클래스 내에 속해있지만 같은 함수명을 가져야 했구나... 거의 2시간동안 오류가 난 것이 죄다 printProd 메소드때문이어서 당분간 쟤랑 좀 절교해야겠다.

 

+ Recent posts