<jupyter_start><jupyter_text>summary- function    - docstring    - scope: 전역, 지역 :global    - inner function: 함수안에 함수를 선언    - lambda function: 간략한 함수를 한줄의 코드로 작성    - dacorlator: 특정 기능을 데코레이터 함수로 만들어 함수에 특정 기능을 적용하는 방법- class    - 변수와 함수들이 모여있는 집합    - 기본 클래스 사용법        - 클래스 선언 -> 객체로 만들고 -> 객체에 함수를 호출    - 생성자 함수        - 클래스가 객체로 만들어질때 객체에 선언되는 변수를 설정하는 방법<jupyter_code>user_datas = [
    {"user":"test","pw":"1234","count":0},
    {"user":"python","pw":"5678","count":0},
]
ls=["a","b","c"]
print(list(range(len(ls))))
print(list(zip(range(len(ls)),ls)))
for idx,data in list(zip(range(len(ls)),ls)):
    print(idx,data)
# user data를 이력받아서 아이디와 패스워드를 체크하는 데코레이터 함수를 코드로 작성
# 로그인 할때마다 count를 1씩 증가
def need_login(func):
    def wrapper(*args,**kargs):
        # 아이디 패스워드 입력
        user, pw=tuple(input("insert user pw: ").split(" "))
        
        # 존재하는 아이디, 패스워드 확인
        #for idx, user_data in zip(range(len(user_datas)),user_datas):
        for idx, user_data in enumerate(user_datas):
            if (user_data["user"]==user) and (user_data["pw"]==pw):
                user_datas[idx]["count"]+=1
                # 함수 실행
                return func(*args,**kargs)
        return "wrong login data!"
        # 카운트 증가 및 함수 실행
    return wrapper
@need_login
def plus(num1,num2):
    return num1+num2
plus(1,2)
user_datas
list(enumerate(user_datas))
# 인덱스하고 데이터를 같이 넣어주는,,
# 스타크래프트의 마린을 클래스로 설계
# 체력(health:40), 공격력(attack_pow:5), 공격(attack())
# 마린 클래스로 마린 객체 2개를 생성해서 마린 1이 마린 2를 공격하는 코드 작성
# attack(self,unit)
class Marine:
    
    def __init__(self,max_health=40,attack_pow=5):
        self.health=max_health
        self.max_health=max_health
        self.attack_pow=attack_pow
    def attack(self,unit):
        unit.health-=self.attack_pow
        if unit.health <= 0:
            unit.health=0
            print("사망")<jupyter_output><empty_output><jupyter_text>위 처럼 작성한다면 객체를 생성하면서 health와 attack_pow를 설정할 수 있음아래와 같이 작성한다면 생성하면서 설정은 못하고 생성한 후 설정해야함marine_1.health=50 이렇게```class Marine:        def __init__(self):        self.health=40        self.attack_pow=5    def attack(self,unit):        unit.health-=self.attack_pow```<jupyter_code>marine_1=Marine()
marine_2=Marine()
marine_1.attack(marine_2) # 여러번 공격하면 marine_2의 체력 계속 감소
#  40 35 가 되도록
marine_1.health,marine_2.health
# 메딕 : heal_pow, heal(unit)
# max.health를 추가해 줌으로써 공격을 받아도 최대 힐량은 동일하게 유지됨
class Medic:
    
    def __init__(self, max_health=40,heal_pow=6):
        self.health=max_health
        self.max_health=max_health
        self.heal_pow=heal_pow
    
    def heal(self,unit):
        if unit.health>0:
            unit.health+=self.heal_pow
            if unit.health>=unit.max_health:
                unit.health=unit.max_health
        else:
            print("사망")
medic= Medic()
marine_1.health,marine_2.health
medic.heal(marine_2)
marine_3=Marine(attack_pow=25)

# __init__(self):
# self.health=40
# selg.attack_pow=5
# 로 Marine클래스가 생성되었다면
# 먼저 객체 생성후 marine_3.attack_pow=25이렇게설정 가능
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)
# 상속을 사용하여 minus함수 추가
class Calculator3(Calculator):
    def minus(self):
        return self.num1-self.num2
calc3 =  Calulator3(1,2)
calc3.plus(),calc3.minus()
# 메서드 오버라이딩 - class의 일부분만 수정된 class를 만들때
# 만약 class를 새로 생성하는것이 아닌 수정만 할거면
# class Calculator(Calculator): 이렇게 하면 됨
# Calculator4가 생성된 후 Calculator3를 재정의(수정)하는 경우는 드물다고 함
class Calculator4(Calculator3):
    def plus(self):
        return self.num1**2 + self.num2**2
calc4=Calculator4(1,2)
calc4.plus()
# 아이폰 1,2,3
# 아이폰1: calling :print("calling")
# 아이폰2: sending
# 아이폰3: internet
class iphone1:
    def calling(self):
        print("calling")
class iphone2(iphone1):
    def send_msg(self):
        print("send_msg")
class iphone3(iphone2):
    def internet(self):
        print("internet")
phone=iphone3()
phone.calling(), phone.send_msg(), phone.internet()<jupyter_output>calling
send_msg
internet<jupyter_text>다중 상속 (보통 2~3단계정도 까지만 상속함)<jupyter_code>class Galaxy:
    def show_img(self):
        print("show_img")
class DssPhone(iphone3,Galaxy):
    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- 부모 클래스에서 사용된 함수의 코드를 가져다가 자식 클래스의 함수에서 재사용할때 사용- 부모 클래스 수정시 plus가 쓰인 함수도 수정됨..```class A:    def plus(self):        code1        class B(A):    def minus(self):        code1 super().plus()        code2```<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
# super(type,object) 다중상속이 아닌이상 꼭 쓸필요는 없지만 명시적으로사용
# 다중상속의 경우 어떤 클래스에서 가져오는지 모를수 있으니까 써줘야함

class Marine2(Marine):
    
    def __init__(self):
        #self.health=40
        #self.attack_pow=5
        super().__init__()
        self.max_health=40
marine=Marine2()
marine.health
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,last_name):
        self.first_name=first_name
        self.last_name=last_name
        
    def disp(self):
        print(self.first_name,self.last_name)
user1=User("andy","kim")
user1.disp()
user1.first_name="jhon"
user1.disp()
user1.first_name=1
user1.disp()
# 제약조건을 걸어줌 (위의경우 이름인데 숫자1이 들어가면 이상하니까)
class User:
    
    def __init__(self,first_name):
        self.first_name=first_name
    
    def setter(self,first_name):
        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)
    
# name이라는 변수에 getter setter로 접근할 수 있게 해주는..
user1=User("andy")
user1.first_name
# setter 함수 실행
user1.name="jhon"
# getter함수 실행 
# 저장은 소문자이지만 출력만 upper효과 나타남
user1.name
user1.first_name<jupyter_output><empty_output><jupyter_text>4. non public- mangling 이라는 방법으로 다이렉트로 객체의 변수에 접근하지 못하게 하는 방법<jupyter_code>class Calculator:
    def __init__(self,num1,num2):
        self.num1=num1
        self.num2=num2
        
    def getter(self):
        return self.num2
    
    # num2에 0이 들어가지 않도록 함
    def setter(self,num2):
        num2=1 if num2 == 0 else num2
        self.num2=num2
    
    def div(self):
        return self.num1/self.num2
    
    number2=property(getter,setter)
calc=Calculator(1,2)
calc.div()
calc.number2
calc.number2=0
calc.number2
calc.num2=0
# 에러가 남 num2를 이용했기 때문에 getter setter를 거치지 않고 
# 다이렉트로 0이 들어갔기 떄문
# number2는 getter setter 에 접근하게 함
calc.div()
# 그렇다면 항상 setter를 거치게 하려면 ->mangling
class Calculator:
    def __init__(self,num1,num2):
        self.num1=num1
        self.__num2=num2
        
    def getter(self):
        return self.__num2
    
    # num2에 0이 들어가지 않도록 함
    def setter(self,num2):
        num2=1 if num2 == 0 else num2
        self.__num2=num2
    
    def div(self):
        return self.num1/self.__num2
    
    number2=property(getter,setter)
calc=Calculator(1,2)
calc.div()
calc.number2
calc.number2=0
calc.number2
# num2가 없다고 나옴
calc.__num2
# __를 붙여서 쓰면 자동으로 _class__object꼴로 저장되는,,
calc._Calculator__num2
# 이름이 바뀌어 저장되기 때문에 num2에 직접접근이 불가능
calc.num2=3
calc.num2
# 위 경우 num2라는 변수 새로 만든것 __num2가된는게 아님
calc.div()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11543303121852971, 'fraction_numerical': 0.028575025176233636, 'mean_word_length': 3.055640632976008, 'pattern_counts': {'":': 6, '<': 30, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '145480', 'license': 'MIT', 'n_tokens_mistral': 3863, 'n_tokens_neox': 4407, 'n_words': 678, 'path': 'python/Class2_01~03.ipynb', 'repo_name': 'Seoheesu1/TIL', 'size': '7944'}