[TIL] Scope, Class

Hailee·2020년 11월 22일
0

[ TIL ]

목록 보기
14/40
post-thumbnail

class위주로 코드를 작성하는 것을 Object Oriented Programming(객체 지향 프로그래밍)이라고 하며,
그 내부에서 쓰일 객체들의 범위를 Scope라 한다.

이것 때문에 그 어떤 언어를 배우던지간에 맨날 객체~객체~~ 그랬던 것!

이 개념이 덜 잡혔을 땐 그놈의 객체지향형 객체 지향 그놈의 객체!!라고 생각했는데
지금은 이래서 객체지향^^.. 구래..^^ 이정도 느낌까지는 온 것 같다
각설하고 공부정리하자

Scope

scope : 범위

  • 어떠한 객체(변수, 함수 등)가 유효한 범위
    : 범위를 넘어가면 해당 객체는 사용될 수 없다

변수나 함수선언된 지점동일한 level의 지역, 그리고 더 안쪽의 지역들까지 범위가 유효하다!
이제 scope에 대한 더 상세한 개념들을 정리해보쟈

Local Scope : 지역변수

  • 특정 범위 내에서만 유효
  • 함수 내부에서 선언된 변수나 중첩 함수의 범위

Enclosing Scope

  • 중첩함수가 있을 때 적용되는 범위
  • 부모 함수에서 선언된 변수는 중첩함수 내에서도 유효

Global Scope : 전역변수

  • 함수 밖에서 선언된 함수, 변수
  • global scope를 가지는 변수, 함수들은 해당 파일에서 가장 바깥쪽에 선언되므로
    해당 파일 내에서 선언된 지점 이후로는 늘 유효

Built-in Scope

  • 파이썬 자체에 내장되어 있는, 파이썬이 제공하는 함수/속성
  • 따로 선언하지 않아도 모든 파이썬 파일 내에서 유효
  • list 및 자료구조들의 element 총 갯수를 리턴해주는 len( ) 함수도 built-in scope를 가진다

Shadowing

파이썬에서 변수, 함수의 정의를 찾을 때 scope들이 검색되는 순서

Local -> Enclosing -> Global -> Built-in

가장 좁은 유효범위 ~ 넓은 범위 순으로
사용되는 변수, 함수의 정의를 찾는다

** Shadowing 효과

  • 동일한 이름의 변수가 서로 다른 scope 내에서 선언이 되면,
    더 좁은 범위에 있는 변수/함수가 더 넓은 범위의 변수를 가리게 된다.

    한마디로 전역변수가 있더라도 함수 내부에 변수를 선언하면
    전역변수의 값은 인식하지 못하는 것처럼!

Class

클래스란 추상적인 개념으로, 없이도 코드를 구현할 수 있지만
코드의 구조를 더 효과적으로 구현할 수 있기 때문에 class를 사용한다

이처럼 class위주로 코드를 작성하는 것을 Object Oriented Programming(객체 지향 프로그래밍)이라고 한다!

class

  • 추상적인, 큰 틀의 개념 같은 것!
  • comedian이라는 큰 틀의 추상적인 개념(class)안에
    각 개그맨들의 실체(instance)들이 구체화 되어있고,
    이들을 객체(object)라고 한다.
  • 즉 instance == object인데,
    class 내부에 class를 실체화(instantiate) 한 instance들을 object라 부른다고 생각하면 된다!
class Car:
	hyundai = Car()
    bmw = Car()
  • Class명은 대문자로 써줘야 하며 카멜 표기법으로 사용한다
    : ScotchWhiskey
    : SomeReallyLongClassName

Class의 attribute(속성)

  • attribute(속성) : class에 정의되는 공통 요소들
  • class내에서 정의하는 함수(function)는 function이라고 하지 않고 method라고 한다
class Car:
    def __init__(self, maker, model, horse_power):
        self.maker       = maker
        self.model       = model
        self.horse_power = horse_power

👉🏻 각 속성들을 class 내에서 정의하기 위해서 __init__ 이라는 method를 사용한다.

  • init과 같이 __가 단어 앞 뒤로 있는 경우 special methods라고 하며,
    이 중 init메 메서드는 class가 실체화 될 때 사용하는 함수!
hyundai = Car("현대", "제네시스", 500)

  • init 메서드는 명확하게 적어주지 않아도 class를 실체화할 때 자동으로 호출이 된다고 한다
    짱신기

메서드 선언부를 보면, parameter를 self 포함 총 4개를 적어두었는데
왜 호출할 땐 3개만 넘겨준 걸까?

Self

  • self : class의 실체(instance)인 객체(object)!
  • class를 실체화 할 때 해당 객체(self)를 자동으로 __init__ 함수에 넘겨준다
  1. __init__ 메서드는 클래스가 실체화 될 때 자동으로 호출된다
  2. __init__self 파라미터는 클래스가 실제화된 객체를 넘겨줘야 한다
    (파이썬이 자동으로 넘겨줌)
  3. __init__의 self 파라미터는 항상 정의되어있어야하며
    맨 처음 파라미터로 정의해야 한다
class Car:
   def __init__(self, maker, model, horse_power):
       self.maker       = maker
       self.model       = model
       self.horse_power = horse_power

👆🏻👆🏻 요로케 parameter로 넘겨진 값들을 동일한 이름으로 self에 저장하는 데,
이는 객체에 넘겨받은 parameter를 저장하고 실체화해서
__init__ 외에 다른 메서드에서 사용하려고 하는 것!

Class Method

class Car:
    def __init__(self, maker, model, horse_power):
        self.maker       = maker
        self.model       = model
        self.horse_power = horse_power
-
    def honk(self):
        return f"{self.maker} 빠라바라빠라밤"

-__init__ 외에도 self 파라미터를 첫번째로 주고 honk 메서드를 선언하면,
dot Notation 을 사용해서 객체를 호출할 수 있다. 👉🏻 <객체>.<메서드>

hyundai = Car("현대", "제네시스", 500)
hyundai.honk()
> "현대 빠라바라빠라밤"

문제 풀이

  • Database 라는 이름의 class를 구현해 주세요.
  • Database 클래스 내부에 다음의 속성(attribute)들을 선언해주세요.
    • name : database의 이름
    • size : 저장할 수 있는 데이터의 max 사이즈. Size를 넘어서는 데이터를 저장할 수 없다.
  • Database 클래스 내부에 다음의 메소드들을 구현해주세요.
    • insert
    • select
    • update
    • delete

각 메소드들에 대한 설명은 아래와 같습니다.

Insert

  • insert 메소드는 self 외에 2개의 parameter를 받습니다.
    : field와 value 입니다.
  • Field 는 저장하고자 하는 데이터의 필드명 이고 value는 값입니다.
  • Field 와 value는 내부적으로 dictionary에 저장되어야 합니다.
  • insert 메소드는 다음 처럼 호출 할 수 있습니다.
# 객체 이름이 db 라는 가정하에
db.insert("name", "정우성")
  • insert 메소드는 특별한 리턴값은 없습니다.
  • 만일 내부 dictionary의 총 사이즈가 database 클래스의 size 속성보다 크면 더이상 새로운 값들을 저장하지 말아야 합니다.

Select

  • select 메소드는 self 외에 1개의 parameter를 받습니다.
    : field 입니다.
  • Field 는 읽고자 하는 데이터의 필드명 입니다.
  • 내부적으로 데이터를 저장하고 있는 dictionary에서 해당 field에 해당하는 키와 연결되어 있는 값을 리턴해주어야 합니다.
  • 예를 들어, 이미 name이라는 필드명으로 "정우성" 이라는 값을 저장했다고 한다면:
# 객체 이름이 db 라는 가정하에
db.select("name")
"정우성"

이 되어야 합니다.

  • 만일 해당 필드값으로 저정되어 있는 값이 없다면 None 을 리턴해주세요.

Update

  • Self 외에 2개의 parameter를 받습니다.
  • field와 value 입니다.
  • 이름 그대로 이미 저장되어 있는 값을 수정하는 메소드 입니다.
# 객체 이름이 db 라는 가정하에
db.update("name", "아이유")
  • 만일 field값에 해당하는 데이터가 저장되어 있지 않으면 아무것도 하지 않습니다.
  • 그리고 특별한 리턴 값은 없습니다.

Delete

  • delete 메소드는 self 외에 1개의 parameter를 받습니다.
    : field 입니다.
  • Field 는 지우고자 하는 데이터의 필드명 입니다.
# 객체 이름이 db 라는 가정하에
db.delete("name")
  • 만일 field값에 해당하는 데이터가 저장되어 있지 않으면 아무것도 하지 않습니다.
  • 그리고 특별한 리턴 값은 없습니다.

혼자서는 도저히 못짜겠어서 선배기수 velog를 찾아버렸다(그래도 insert method 이후로는 혼자 작성함ㅎㅎ)

내가 짠 코드

class Database:
  def __init__(self, name, size):
    self.name = name
    self.size = size
    self.db = {}        # 내부 딕셔너리
 - 
  def insert(self, field, value):
    # my_dict = {"필드명": self.field, "값": self.value}
    if len(self.db) < self.size:
      self.db[field] = value
-
  def select(self, field):
    if field in self.db:
      return self.db[field]
    else:
      return "None"
-
  def update(self, field, value):
    if field in self.db:
      self.db[field] = value
-
  def Delete(self, field):
    if field in self.db:
      del self.db[field]   

처음엔 insert 메서드 문제만 보고, db라는 dictionary를 insert 메서드 내에 선언했었는데
알고보니 모든 메서드에서 사용해야 하는 dictionary였기 때문에
init 메서드에 선언해야 했다.

delete는 del 하고 dictionary명+[키] 이렇게 해준다는거 알쥐알쥐


하지만 해당 코드는 👆🏻 어마무시한 에러가 납니다
왜?
delete 메서드명을 대문자로 써놨기 때문^^

고쳤떠니 또 에러가 뜬다👇🏻👇🏻
왜?!

insert부분에서 리턴해주는 값이 그냥 None이어야하는데,
난 문자열로 리턴해주고 있기 때문!

고쳤는데 역시나 또 에러가 난다 👇🏻👇🏻👇🏻
왜,,? 😞😞😞

암만 생각해도 코드는 문제가 없는데,
이미 1 != 185라는 AssertionError가 났다는 건
어찌됐든 내 db라는 dictionary에서 1이라는 값을 찾았다는 것 아닌가
그럼 이건 채점하는 값이 문제인가 싶어서
~~이래도 되려나 싶긴 했지만 ~~채점하는값을 185에서 1로 바꾸어주었더니 통과했다

괜찮은거겠지..?

profile
웹 개발 🐷😎👊🏻🔥

0개의 댓글