<jupyter_start><jupyter_text>저번요약- funtion    - docstring    - scope : 전역, 지역 : global 예약어를 사용    - inner function : 함수안에 함수를 선언 -> 지역함수를 사용을하려면 return을 사용    - lambda function : 간략한 함수를 한줄의 코드로 작성    - Decorlator : 특정 기능을 데코레이터함수로 만들어 함수에 특정 기능을 적용하는 방법- class    - 변수와 함수들이 모여있는 집합    - 기본 클래스 사용법         - 클래스 선언 -> 객체로 만듦 -> 객체에 함수를 호출    - 생성자 함수         - 클래스가 객체로 만들어질때 객체에 선언되는 변수를 설정하는 방법        - __init__, self. =<jupyter_code># 문제 1.
user_datas = [
    {"user":"test", "pw":"1234", "count":0},
    {"user":"python", "pw":"5678", "count":0},
]

user_datas[0]["count"]
list(enumerate(user_datas))
# user_datas를 입력받아서 아이디와 패스워드를 체크하는 데코레이더 함수를 코드로 작성하시오
# 로그인이 될때마다 count를 증가
### 데코레이터 함수
def need_login(func):
    
    def wrapper(*args, **kwargs):
        
        # 아이디, 패스워드 입력
        user, pw = tuple(input("insert user pw : ").split(" "))
        
        # 존재하는 아이디, 패스워드 확인
        # for idx, user_data in zip(range(len(user_datas)), user_datas):
        # enumerate함수 사용해서 코드 작성
        for idx, user_data in list(enumerate(user_datas)):
            if (user_data["user"] == user) and (user_data["pw"] == pw):
                # count 횟수 데이터 추가
                user_datas[idx]["count"] += 1
                # 함수 실행
                return func(*args, **kwargs)
        return "not allow!!"
    return wrapper
@need_login
def plus(num1, num2):
    return num1 + num2
plus(1, 2)
user_datas
class Marine:
    
    def __init__(self, health = 40, attack_pow = 5):
        self.health = health
        self.attack_pow = attack_pow
    
    def attack(self, unit):
        unit.health -= self.attack_pow
        if unit.health <= 0:
            unit.health = 0
            print("사망")
marine_1 = Marine()
marine_2 = Marine()
marine_1.attack(marine_2) # 여러번 공격하면 marine_2의 체력이 계속 감소
marine_1.health, marine_2.health # 40, 35<jupyter_output><empty_output><jupyter_text>메딕 : heal_pow, heal(unit)<jupyter_code>class Medic:
    
    def __init__(self, health = 40, heal_pow = 6):
        self.health = health
        self.heal_pow = heal_pow
        
    def heal(self, unit):
        if unit.health > 0:
            unit.health += self.heal_pow
            if unit.health >= 40:
                unit.health = 40
        else:
            print("이미 사망")
medic = Medic()
marine_1.health, marine_2.health
medic.heal(marine_2)
marine_3 = Marine(attack_pow=30)
marine_3.attack(marine_1)
marine_1.health<jupyter_output><empty_output><jupyter_text>1. 상속- 클래스의 기능을 가져다가 수정하거나 추가할때 사용하는 방법<jupyter_code>class Calculator:
    
    def __init__(self, num1, num2):
        self.num1 = num1
        self.num2 = num2
        
    def plus(self):
        return self.num1 + self.num2
calc = Calculator(1, 2)
calc.plus()
# minus 기능을 추가한 계산기
class Calculator2:
    
    def __init__(self, num1, num2):
        self.num1 = num1
        self.num2 = num2
        
    def plus(self):
        return self.num1 + self.num2
    
    def minus(self):
        return self.num1 - self.num2
calc2 = Calculator2(1, 2)
calc2.plus(), calc2.minus()
# Calculator를 상속받아서 minus함수를 추가한 Calculator3를 작성 -> 상속
class Calculator3(Calculator):
    
    def minus(self):
        return self.num1 - self.num2
calc3 = Calculator3(1, 2)
calc3.plus(), calc3.minus()<jupyter_output><empty_output><jupyter_text>메서드 오버라이딩- 특정함수를 변경하고싶을떄<jupyter_code># 메서드 오버라이딩
class Calculator4(Calculator3):
    def plus(self):
        return self.num1**2 + self.num2**2
calc4 = Calculator4(1, 2)
calc4.plus(), calc4.minus()<jupyter_output><empty_output><jupyter_text>문제 3.- 아이폰 1, 2, 3- 아이폰 1 : calling -> print("calling")- 아이폰 2 : send msg 추가- 아이폰 3 : internet 추가<jupyter_code>class Iphone:
    def calling(self):
        print("calling")
class Iphone2(Iphone):
    def send_msg(self):
        print("send msg")
class Iphone3(Iphone2):
    def internet(self):
        print("internet")
iphone3 = Iphone3()
iphone3.calling(), iphone3.send_msg(), iphone3.internet()<jupyter_output>calling
send msg
internet<jupyter_text>다중 상속<jupyter_code>class Galuxy:
    def show_img(self):
        print("show_img")
class DssPhone(Iphone3, Galuxy):
    def camera(self):
        print("camera")
dss_phone = DssPhone()
[func for func in dir(dss_phone) if func[:2] != "__"]<jupyter_output><empty_output><jupyter_text>2. super- 부모클래스에서 사용된 함수의 코드를 가져다가 자식클래스의 재사용할때 사용```class A:    def plus(self):        code1        class B(A):    def minus(self):        code1  super().plus()        code2``````code1이 중복 => super().plus()로 사용하면 code1이 된다.```<jupyter_code>class Marine:
    
    def __init__(self):
        self.health = 40
        self.attack_pow = 5
    
    def attack(self, unit):
        unit.health -= self.attack_pow
        if unit.health <= 0:
            unit.health = 0
class Marine2(Marine):
    
    def __init__(self):
        # self.health = 40
        # self.attack_pow = 5 # 위 두 줄 코드가 중복 ==> super로 대체해서 작성
        super().__init__() # 위 두줄을 쓴것과 같은의미
                           # 다중 상속을 받을경우 어디서 가져오는지를 알기위해서 Marine처럼 명시적으로 작성
        self.max_health = 40
marine = Marine2()
marine.health, marine.attack_pow, marine.max_health<jupyter_output><empty_output><jupyter_text>3. class의 getter, setter- 객체의 내부 변수에 접근할때 특정 로직을 거쳐서 접근시키는 방법<jupyter_code>class User:
    
    def __init__(self, first_name):
        self.first_name = first_name
        
    # 제약조건을 걸어준다 -> getter, setter
    def setter(self, first_name):
        print("setter")
        if len(first_name) >= 3:
            self.first_name = first_name
        else:
            print("error")
            
    def getter(self):
        print("getter")
        return self.first_name.upper()

    name = property(getter, setter) # property : getter, setter로 접근할수 있도록하는 함수
user1 = User("andy")
user1.first_name
# setter 함수 실행
user1.name = "jhone"
# getter함수 실행
user1.name<jupyter_output>getter<jupyter_text>4. non public- mangling이라는 방법으로 다이렉트로 객체의 변수에 접근하지 못하게 하는 방법<jupyter_code>class Calculator:
    
    def __init__(self, num1, num2):
        self.num1 = num1
        self.__num2 = num2 # __로 mangling설정
        
    def getter(self):
        return self.__num2
    
    # num2에 0이 들어가지 않도록 함
    def setter(self, num2):
        num2 = 1 if num2 == 0 else num2 # 삼항연산자를 사용
        self.__num2 = num2
        
    def __disp(self): # 함수이름에 __를 붙여서 private형으로 변형
        print(self.num1, self.__num2)
        
    def div(self):
        self.__disp()
        return self.num1 / self.__num2
    
    number2 = property(getter, setter)
calc = Calculator(1, 2)
calc.div()
# getter 실행
calc.number2
# calc.num2 # 에러발생 - num2변수가 mangling으로 인해서 private형태로 되어있기때문이다.
# setter 실행
calc.number2 = 0
calc.number2
# calc.__num2 # 다이렉트 접근 불가
calc._Calculator__num2 = 0 # 이렇게 다이렉트로 접근가능 => 굳이 이렇게 넣을 필요가 없다.
calc.div()
calc._Calculator__disp()<jupyter_output>1 1<jupyter_text>5. is a & has a- 클래스를 설계하는 개념- A is a B     - A는 B이다. 상속을 이용해서 클래스를 만드는 방버- A has a B    - A는 B를 가진다. A가 B객체를 가지로 클래스를 만드는 방법<jupyter_code># 사람클래스 : 이름, 이메일, 정보출력()
# is a로 만드는 방법
class Person:
    
    def __init__(self, name, email):
        self.name = name
        self.email = email
class Person2(Person):
    def info(self):
        print(self.name, self.email)
p = Person2("andy", "<EMAIL>")
p.info()
# has a로 만드는 방법
class Name:
    def __init__(self, name):
        self.name_str = name
        
class Email:
    def __init__(self, email):
        self.email_str = email
class Person:
    def __init__(self, name_obj, email_obj):
        self.name = name_obj
        self.email = email_obj
        
    def info(self):
        print(name.name_str, email.email_str)
name = Name("andy")
email = Email("<EMAIL>")
p = Person(name, email) # 객체를 넣어준다.
p.info()<jupyter_output>andy <EMAIL><jupyter_text>Magic(Special) Method- compare    - `__eq__` : ==를 의미    - `__ne__` : !=를 의미    - `__lt__` : <를 의미- calculate    - `__add__` : +    - `__sub__` : -- `__repr__` : 객체의 내용을 출력(개발자용)- `__str__` : 객체의 내용을 출력<jupyter_code>"test" == "test"
"test".__eq__("test")
class Txt:
    def __init__(self, txt):
        self.txt = txt
        
    def __eq__(self, txt_obj):
        return self.txt.lower() == txt_obj.txt.lower()
    
    def __repr__(self):
        return "Txt(txt={})".format(self.txt)
    
    def __str__(self):
        return self.txt
t1 = Txt("python")
t2 = Txt("Python")
t3 = t1
t1 == t2, t1 == t3, t2 == t3
print(t1)
t1
range(5) # __repr__이 range(0, 5)로 출력되게 정의되어있는 것이다.<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12203268519623046, 'fraction_numerical': 0.023499940355481332, 'mean_word_length': 2.563110922226944, 'pattern_counts': {'":': 6, '<': 47, '<?xml version=': 0, '>': 56, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '622567', 'license': 'MIT', 'n_tokens_mistral': 3801, 'n_tokens_neox': 4260, 'n_words': 787, 'path': 'Python/python/07_class_2.ipynb', 'repo_name': 'kimchangkyu/TIL', 'size': '8404'}