Special method (magic)

Haks.·2024년 12월 5일
0

Study

목록 보기
3/65

📝 Special 메소드


  • 파이썬의 핵심 4가지

    • 시퀀스(Sequence), 반복(Iterator), 함수(Functions), 클래스(Class)
  • 클래스 안에 정의 할 수 있는 특별한(Built-in) 메소드

  • namedtuple : 튜플 형태인데 key와 value 를 갖고잇는 함수

  • from collections import namedtuple
    * 선언방법
     ```
       Point1 = namedtuple('Point',['x','y'])
       Point2 = namedtuple('Point', 'x, y')
       Point3 = namedtuple('Point', 'x y')
       Point4 = namedtuple('Point', 'x y x class', rename=True) # Default = False ,중복과 class 라는 것을 이미 있는 예약어를  바꾸는것을 허용해줌
       p5 = Point3(**temp_dict) # 딕셔너리 언팩킹 x,y 가 key 값인 것 이런식으로 사용가능
     * 부를때
       p1 = Point1(x = 10, y = 35)
       p2 = Point2(20, 40)
       p3 = Point3(45, y = 20)
       p4 = Point4(10, 20, 30, 40) -> Point(x=10, y=20, _2=30, _3=40) 난수로 나옴
       ```
  • _make() : 새로운 객체 생성, 리스트를 네임드 튜플로 변환시키는 함수, 값이 딱 맞아야 사용 가능
  • temp = [52,38]

    p4 = Point1._make(temp)
  • _fields : 매직메소드 성의 메소드 , key가 뭐있는지 조회
  • _asdict() : OrderedDict(정렬된 딕셔너리) 반환,네임드 튜플을 딕셔너리로 반환 하는것

# Tip


  • 클래스 안의 함수에서 return 해줄때 새로운 클래스의 값으로 반환 해줄 수 있음
  • 클래스명.__doc__ 밑에 주석처리 해놓은 부분을 보여줌
  • 이것을 활용해서 각 함수 밑에 설명 해놓을 수있음
  • 객체.__init.__doc

💻 코딩 실습


# 기본형
print(int)
print(float)

print(dir(int))
print(dir(float))

n= 10

print(n + 100) # 내부적인 add 가 호출된거임
print(n.__add__(100))
# print(n.__doc__) # int 가 의미하는게 정확히 뭔지 coment
print(n.__bool__())
print(n*100 ,n.__mul__(100))
<class 'int'>
<class 'float'>
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
['__abs__', '__add__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getformat__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__setformat__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'as_integer_ratio', 'conjugate', 'fromhex', 'hex', 'imag', 'is_integer', 'real']
110
110
True
1000 1000

class Fruit :
    def __init__(self,name,price):
        self._name = name
        self._price = price

    def __str__(self) :
        return 'Fruit Class info : {} , {}'.format(self._name,self._price)

    def __add__(self,x): # 받아오는 변수가 같은 클래스의 다른 객체임 그래서 x._price
        print('called __add__')
        return self._price + x._price
    def __sub__(self,x):
        print('called __sub__')
        return self._price -x._price
    def __le__(self,x) : #대소비교
        print('called __le')
        if self._price <=x._price:
            return True
        else:
            return False
    def __ge__(self,x) :
        print('callse __ge__')
        if self._price >=x._price :
            return True
        else :
            return False

# 인스턴스 생성
s1 = Fruit('Orage', 7500)
s2 = Fruit('Banna', 3000)

# print(s1._price + s2._price)# 일반적인 계산

print(s1 + s2) ## 매직메소드를 클래스 안에 구해놓으니까 매직메소드를 사용할때 원하는 것을 더 하게 설정 해 놓아 줄 수 있음 + 를 햇지만 다른것으로 호출시킬수도 있음

# 매직 메소드
print(s1>=s2)
print(s1<=s2)
print(s1-s2)
print(s1,s2)
called __add__
10500
callse __ge__
True
called __le
False
called __sub__
4500
Fruit Class info : Orage , 7500 Fruit Class info : Banna , 3000
from inspect import ArgSpec

# 벡터 (x,y)
#(5,2) + (4,3) = (9,5) 가 되게 매직메소드 만들려함
# (10,3) * 5 = (50,15)
# max((5,10)) =10

class Vector():
    def __init__(self,*args) :
        '''
        Create a vector, example : v = Vector(5,10)
        '''
        if len(args) ==0 :
            self._x, self._y = 0,0
        else :
            self._x, self._y = args
    def __repr__(self):
        '''Return the vector informations.'''
        return 'Vector(%r, %r)' % (self._x, self._y)

    def __add__(self,other) :
        '''Return the vector addtion of self and other'''
        return Vector(self._x + other._x, self._y + other._y) # 새로운 벡터 클래스로 반환
    def __mul__(self,y) :
        '''Return the vector multiply of self and other'''
        return Vector(self._x *y, self._y * y)
    def __bool__(self) : # True False 확인하는 매직메소드 = 0.0인지
        return bool(max(self._x,self._y))

# vector 인스턴스 생성
v1 = Vector(5,7)
v2 = Vector(23,35)
v3 = Vector()

# 매직메소드 출력
print(Vector.__init__.__doc__)
print(Vector.__repr__.__doc__)
print(Vector.__mul__.__doc__)
print()
print(v1,v2,v3)
print(v1 + v2)
print(v1 * 3)
print(bool(v1),bool(v2))
print(bool(v3))


# print(Vector.__init__.__doc__)
Create a vector, example : v = Vector(5,10)
        
Return the vector informations.
Return the vector multiply of self and other

Vector(5, 7) Vector(23, 35) Vector(0, 0)
Vector(28, 42)
Vector(15, 21)
True True
False
ok
# 객체 -> 파이썬의 데이터를 추상화
# 모든 객체 -> id,type _> value

# 일반적인 튜플
pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)

from math import sqrt
l_leng1 = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)

print(l_leng1)

# 네임드 튜플 사용

from collections import namedtuple

# 네임드 튜플 선언
Point = namedtuple('Point','x y')

pt3 = Point(1.0, 5.0) # 포인트라는 네임드 튜플, 튜플 형식, KEY 로 확인할 수도 있구나 'x'면 1.0 'y'면 5.0 인덱스로도 접근가능 [0]이면 x
pt4 = Point(2.5, 1.5)

# print(pt3)
# print(pt4)
# print(pt3[0]) #인덱스로 접근가능하고 키로도 접근가능
# print(pt3.x)  # 키로 접근하는 것이 좀 더 명시적이여서 좋다

l_leng2 = sqrt((pt3.x - pt4.x)**2 + (pt3.y - pt4.y)**2)
print(l_leng2)

# 튜플 선언 방법 1
Point1 = namedtuple('Point',['x','y'])
Point2 = namedtuple('Point', 'x, y')
Point3 = namedtuple('Point', 'x y')
Point4 = namedtuple('Point', 'x y x class', rename=True) # Default = False

print(Point4)

# Dict to Unpacking
temp_dict = {'x' : 75, 'y': 55}

p1 = Point1(x = 10, y = 35)
p2 = Point2(20, 40)
p3 = Point3(45, y = 20)
p4 = Point4(10, 20, 30, 40)
p5 = Point3(**temp_dict) # 딕셔너리 언팩킹

print()

print(p1)
print(p2)
print(p3)
# rename 테스트
print(p4)
print(p5)

# 사용
print(p1[0] + p2[1])
print(p1.x + p2.y)

# Unpacking
x, y = p2
print (x,y)

# 네임드 튜플 메소드
temp = [52,38]

# _make() : 새로운 객체 생성, 리스트를 네임드 튜플로 변환시키는 함수, 값이 딱 맞아야 사용 가능
p4 = Point1._make(temp)

print(p4)

# _fileds : 필드 네임 확인
print(p1._fields,p2._fields,p3._fields)

# _asdict() : OrderedDict(정렬된 딕셔너리) 반환
print(p1._asdict())
print(p4._asdict())
3.8078865529319543
3.8078865529319543
<class '__main__.Point'>

Point(x=10, y=35)
Point(x=20, y=40)
Point(x=45, y=20)
Point(x=10, y=20, _2=30, _3=40)
Point(x=75, y=55)
50
50
20 40
Point(x=52, y=38)
('x', 'y') ('x', 'y') ('x', 'y')
{'x': 10, 'y': 35}
{'x': 52, 'y': 38}
# 실 사용 실습
# 반 20명, 4개의 반 (A,B,C,D) B14,B15 번학생 번호부여가능

Classes = namedtuple('Classes',['rank','number'])

# 그룹 리스트 선언
numbers = [str(n) for n in range(1,21)]
ranks = 'A B C D'.split() # 공백을 기준으로 나눔

students = [Classes(rank,number) for rank in ranks for number in numbers]

print(len(students))

# 추천

students2 = [Classes(rank,number)
            for rank in 'A B C D'.split()
                for number in [str(n)
                    for n in range(1,21)]]

for s in students2 :
    print(s)
80
Classes(rank='A', number='1')
Classes(rank='A', number='2')
Classes(rank='A', number='3')
Classes(rank='A', number='4')
....~~

0개의 댓글

관련 채용 정보