μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리)

 

 

<이전 κΈ€>

https://silvercoding.tistory.com/27

 

[python 심화] 10. copy & deep copy

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리) <이전 κΈ€> https://silvercoding.tistory.com/26 https://silvercoding.tistory.com/25 이번 ν¬μŠ€νŠΈμ—μ„œλŠ” λ°μ½”λ ˆμ΄ν„°λ₯Ό μ•Œμ•„λ³Ό 것이닀. λ°μ½”λ ˆμ΄ν„°λŠ” μ–΄λ ΅λ‹€κ³  느..

silvercoding.tistory.com

 

 

 

- Class  Getter & Setter 

* 클래슀 μ„ μ–Έ 

class VectorP(object):
    def __init__(self, x, y):
        self.__x = float(x)
        self.__y = float(y)

    def __iter__(self):
        return (i for i in (self.__x, self.__y)) # Generator

 

 

* 객체 μ„ μ–Έ 

v = VectorP(20, 40)

 

* 였λ₯˜

print('EX1-1 - ', v.__x, v.__y)  # ---> 직접 μ ‘κ·Ό λΆˆκ°€

 AttributeError: 'VectorP' object has no attribute '__x' 

 μ–Έλ”λ°” 2개둜 μ„ μ–Έν•œ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λŠ” 객체λ₯Ό ν†΅ν•œ 직접 접근이 λΆˆκ°€λŠ₯ ν•˜λ‹€. 

 

 

 

 

- Getter & Setter 

: 더 μ•ˆμ „ν•œ ν”„λ‘œκ·Έλž˜λ°μ„ ν•  수 μžˆλ‹€. 

class VectorP(object):
    def __init__(self, x, y):
        self.__x = float(x)
        self.__y = float(y)

    def __iter__(self):
        return (i for i in (self.__x, self.__y)) # Generator

    @property
    def x(self):
        print('Called Property X')
        return self.__x

    @x.setter
    def x(self, v):
        print('Called Property X setter')
        self.__x = float(v)
    
    @property
    def y(self):
        print('Called Property Y')
        return self.__y

    @y.setter
    def y(self, v):
        print('Called Property Y setter')        
        if v < 30: 
            raise ValueError('30 Below is not possible')
        self.__y = float(v)

λ°μ½”λ ˆμ΄ν„°λ₯Ό μ‚¬μš©ν•˜μ—¬ @property, @x.setter @y.setter 밑에 x와 yλ₯Ό μ •μ˜ν•΄ μ€€λ‹€. 

 

 

print('EX1-2 - ', dir(v), v.__dict__)
v.x = 10
print('EX1-3 - ', v.x, v.y)

 EX1-2 -  ['_VectorP__x', '_VectorP__y', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'x', 'y'] {'_VectorP__x': 20.0, '_VectorP__y': 40.0} 
 Called Property X 
 Called Property Y 
 EX1-3 -  10.0 40.0 

Getter와 Setterλ₯Ό μ΄μš©ν•˜μ—¬ self.__x λ³€μˆ˜μ— self.x 의 ν˜•νƒœλ‘œ 접근이 κ°€λŠ₯ν•΄ μ‘Œλ‹€. v.x=10 을 μ΄μš©ν•˜μ—¬ 값을 λ°”κΏ€ 수 μžˆλŠ” 것 λ˜ν•œ λ³Ό 수 μžˆλ‹€. 

 

# Iter 확인 
for val in v:
    print('EX1-4 - ', val)

 EX1-4 -  10.0 
 EX1-4 -  40.0 

κ΅¬ν˜„ν•΄ 놓은 __iter__ λ©”μ†Œλ“œλ₯Ό ν™•μΈν•˜μ˜€λ‹€. 

 

 

 

- __slot__ 

: 파이썬 μΈν„°ν”„λ¦¬ν„°μ—κ²Œ 톡보 , ν•΄λ‹Ή ν΄λž˜μŠ€κ°€ κ°€μ§€λŠ” 속성을 μ œν•œ 

* __dict__ 

: 속성 μ΅œμ ν™” -> λ‹€μˆ˜ 객체 생성 μ‹œ λ©”λͺ¨λ¦¬ μ‚¬μš© 곡간 λŒ€ν­ κ°μ†Œ 

: ν•΄λ‹Ή ν΄λž˜μŠ€μ— λ§Œλ“€μ–΄μ§„ μΈμŠ€ν„΄μŠ€ 속성 관리에 λ”•μ…”λ„ˆλ¦¬ λŒ€μ‹  set ν˜•νƒœλ₯Ό μ‚¬μš© 

 

class TestA(object):
    __slots__ = ('a', )

class TestB(object):
    pass

 

 

* 객체 생성 

use_slot = TestA()
no_slot = TestB()

 

* μ‚¬μš©

print('EX2-1 - ', use_slot)
# print('EX2-2 - ', use_slot.__dict__)  # 속성 κ°’ 확인 --> dictionary이기 λ•Œλ¬Έμ— μ•ˆλ¨ 
print('EX2-3 - ', no_slot)
print('EX2-3 - ', no_slot.__dict__)

 EX2-1 -  <__main__.TestA object at 0x000001BE68801C78> 
 EX2-3 -  <__main__.TestB object at 0x000001BE68A4D6A0> 
 EX2-3 -  {} 

 

 

* λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰ 비ꡐ

import timeit

# 츑정을 μœ„ν•œ ν•¨μˆ˜ μ„ μ–Έ 
def repeat_outer(obj):
    def repeat_inner():
        obj.a = 'TEST'
        del obj.a
    return repeat_inner

obj.a = 'TEST' λ₯Ό μ„ μ–Έν•˜κ³  obj.aλ₯Ό μ‚­μ œν•˜λŠ” μ‹œκ°„μ„ μΈ‘μ •ν•˜κΈ° μœ„ν•œ ν•¨μˆ˜λ₯Ό μƒμ„±ν•œλ‹€. 

 

print(min(timeit.repeat(repeat_outer(use_slot), number=100000))) 
print(min(timeit.repeat(repeat_outer(no_slot), number=100000)))

 0.015717999999999982 
 0.018735899999999972 

100000λ²ˆμ„ λ°˜λ³΅ν•˜μ—¬ κ°€μž₯ μž‘μ€ μ‹œκ°„μ„ 좜λ ₯ν•΄ λ³΄μ•˜μ„ λ•Œ, slot을 μ‚¬μš©ν•œ 클래슀의 객체가 더 λΉ λ₯Έ 것을 μ•Œ 수 μžˆλ‹€. 

 

 

 

- 객체 μŠ¬λΌμ΄μ‹±

class ObjectS:
    def __init__(self):
        self._numbers = [n for n in range(1, 100, 3)]

    def __len__(self):
        return len(self._numbers)

    def __getitem__(self, idx):
        return self._numbers[idx]

μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό 리슀트 νƒ€μž…μœΌλ‘œ μƒμ„±ν•˜κ³ , __len__, __getitem__ λ©”μ†Œλ“œλ₯Ό μ„ μ–Έν•΄ 놓은 ObjectS 클래슀λ₯Ό μƒμ„±ν•œλ‹€. 

 

* 객체 생성

s = ObjectS()

 

print('EX3-1 - ', s.__dict__)    
print('EX3-2 - ', len(s))
print('EX3-3 - ', len(s._numbers))  # __len__ 이 μ—†μœΌλ©΄ . 
print('EX3-4 - ', s[1:100])
print('EX3-5 - ', s[-1])
print('EX3-6 - ', s[::10])

 EX3-1 -  {'_numbers': [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49,  
 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97]} 

 EX3-2 -  33 
 EX3-3 -  33 

__len__ λ©”μ†Œλ“œλ₯Ό μ„ μ–Έν•΄ 놓지 μ•ŠλŠ”λ‹€λ©΄ EX3-3κ³Ό 같이 μž‘μ„±ν•˜μ—¬ 리슀트의 길이λ₯Ό 확인할 수 μžˆλ‹€. 
 EX3-4 -  [4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61,  
 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97] 
 EX3-5 -  97 
 EX3-6 -  [1, 31, 61, 91] 

 

__getitem__ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 객체 μžμ²΄μ—μ„œ 인덱싱과 μŠ¬λΌμ΄μ‹±μ„ κ°€λŠ₯ν•˜κ²Œ λ§Œλ“€μ—ˆλ‹€. λ§Œμ•½ __getitem__ λ©”μ†Œλ“œλ₯Ό μƒμ„±ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ λ‹€μŒκ³Ό 같은 μ—λŸ¬κ°€ λ‚œλ‹€.

 

 Traceback (most recent call last): 
  File "c:/Users/sooki/Desktop/python_high/chapter05_02.py", line 114, in <module>      
    print('EX3-4 - ', s[1:100])
 TypeError: 'ObjectS' object is not subscriptable 

 

 

 

 

- 파이썬 좔상 클래슀 

https://docs.python.org/3/library/collections.abc.html

 

collections.abc — Abstract Base Classes for Containers — Python 3.9.6 documentation

collections.abc — Abstract Base Classes for Containers New in version 3.3: Formerly, this module was part of the collections module. Source code: Lib/_collections_abc.py This module provides abstract base classes that can be used to test whether a class

docs.python.org

1. 자체적으둜 객체 생성 λΆˆκ°€ 

2. 상속을 ν†΅ν•΄μ„œ 'μžμ‹ 클래슀' μ—μ„œ 생성해야 함 

3. 개발과 κ΄€λ ¨λœ κ³΅ν†΅λœ λ‚΄μš© (ν•„λ“œ, λ©”μ†Œλ“œ) μΆ”μΆœ 및 ν†΅ν•©ν•΄μ„œ κ³΅ν†΅λœ λ‚΄μš©μœΌλ‘œ μž‘μ„±ν•˜κ²Œ ν•˜λŠ” 것

 

 

 

** Sequence 상속 받지 μ•Šμ•˜μ§€λ§Œ, μžλ™μœΌλ‘œ __iter__, __contain__ κΈ°λŠ₯ μž‘λ™ 

** 객체 전체λ₯Ό μžλ™μœΌλ‘œ 쑰사 -> μ‹œν€€μŠ€ ν”„λ‘œν† μ½œ 

class IterTestA():
    def __getitem__(self, idx):
        return range(1, 50, 2)[idx] # range(1, 50, 2)

__getitem__ λ©”μ†Œλ“œλ₯Ό μ„ μ–Έν•œ IterTestA 클래슀λ₯Ό μƒμ„±ν•œλ‹€. 

 

 

* 객체 생성

i1 = IterTestA()

 

print('EX4-1 - ', i1[4])
print('EX4-2 - ', i1[4:10])
print('EX4-3 - ', 3 in i1[1:10])  # __contain__ κ΅¬ν˜„ν•˜μ§€ μ•Šμ•„λ„ μ‚¬μš©λ¨ 
print('EX4-4 - ', [i for i in i1]) # κ΅¬ν˜„ν•˜μ§€ μ•Šμ€ __iter__ μ‹€ν–‰

 EX4-1 -  9 
 EX4-2 -  range(9, 21, 2) 
 EX4-3 -  True 
 EX4-4 -  [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49] 

인덱싱과 μŠ¬λΌμ΄μ‹±μ΄ κ°€λŠ₯ν•˜λ„λ‘ __getitem__ λ©”μ†Œλ“œλ§Œ 생성을 ν•΄ λ†“μ•˜μ§€λ§Œ , 4-3, 4-4 κ°€ 싀행이 λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. __contain__κ³Ό __iter__λ©”μ†Œλ“œλ₯Ό 클래슀 내에 μƒμ„±ν•˜μ§€ μ•Šμ•˜μ–΄λ„ 싀행이 된 것이닀. 

 

 

 

 

- Sequence 상속 

: μš”κ΅¬μ‚¬ν•­μΈ μΆ”μƒλ©”μ†Œλ“œλ₯Ό λͺ¨λ‘ κ΅¬ν˜„ν•΄μ•Ό λ™μž‘ 

from collections.abc import Sequence

class IterTestB(Sequence):
    def __getitem__(self, idx):
        return range(1, 50, 2)[idx] # range(1, 50, 2)

    def __len__(self, idx):
        return len(range(1, 50, 2)[idx])

Sequenceλ₯Ό 상속 λ°›λŠ” IterTestB 클래슀λ₯Ό μƒμ„±ν•œλ‹€.  __getitem__, __len__ <--- 이 λ‘κ°œμ˜ λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜μ§€ μ•ŠμœΌλ©΄ λ™μž‘ν•˜μ§€ μ•ŠλŠ”λ‹€. 

i2 = IterTestB()  # ---> __getitem__, __len__ ν•¨μˆ˜κ°€ μ—†μœΌλ©΄ 객체 생성 λΆˆκ°€. (κ°•μ œμ„±μ„ λˆλ‹€.)

λ‘κ°œμ˜ λ©”μ†Œλ“œλ₯Ό ν•˜λ‚˜λΌλ„ κ΅¬ν˜„ν•˜μ§€ μ•ŠμœΌλ©΄ λ‹€μŒκ³Ό 같은 μ—λŸ¬κ°€ λ‚œλ‹€. 

TypeError: Can't instantiate abstract class IterTestB with abstract methods __len__  

 

print('EX4-5 - ', i2[4])
print('EX4-6 - ', i2[4:10])
print('EX4-7 - ', 3 in i2[1:10])

 EX4-5 -  9 
 EX4-6 -  range(9, 21, 2) 
 EX4-7 -  True 

 

 

 

 

 

 

- abc ν™œμš© 예제 

https://docs.python.org/ko/3/library/abc.html

 

abc — 좔상 베이슀 클래슀 — Python 3.9.6 λ¬Έμ„œ

abc — 좔상 베이슀 클래슀 μ†ŒμŠ€ μ½”λ“œ: Lib/abc.py 이 λͺ¨λ“ˆμ€, PEP 3119μ—μ„œ μ„€λͺ…λœ λŒ€λ‘œ, νŒŒμ΄μ¬μ—μ„œ 좔상 베이슀 클래슀 (ABC) λ₯Ό μ •μ˜ν•˜κΈ° μœ„ν•œ 기반 ꡬ쑰λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€; 이것이 μ™œ νŒŒμ΄μ¬μ— μΆ”κ°€λ˜μ—ˆ

docs.python.org

import abc

class RandomMachine(abc.ABC): # metaclass=abc.ABCMeta(3.4 μ΄ν•˜)
    # __metaclass__ = abc.ABCMeta

    #좔상 λ©”μ†Œλ“œ  ---> λ°μ½”λ ˆμ΄ν„°κ°€ 뢙은 건 무쑰건 μžμ‹ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€.
    @abc.abstractmethod
    def load(self, iterobj):
        '''Iterable ν•­λͺ© μΆ”κ°€'''

    # 좔상 λ©”μ†Œλ“œ 
    @abc.abstractmethod
    def pick(self, iterobj):
        '''λ¬΄μž‘μœ„ ν•­λͺ© 뽑기'''

    def inspect(self):
        items = []
        while True:
            try:
                items.append(self.pick())
            except LookupError:
                break
            return tuple(sorted(items))

λ°μ½”λ ˆμ΄ν„°λ‘œ @abc.abstractmethod κ°€ 뢙은 λ©”μ†Œλ“œλŠ” 무쑰건 μžμ‹ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ ν•΄μ£Όμ–΄μ•Ό ν•˜λŠ” λ©”μ†Œλ“œμ΄λ‹€ . load와 pick λ©”μ†Œλ“œμ— λ°μ½”λ ˆμ΄ν„°κ°€ λ‹¬λ €μžˆλ‹€. μœ„μ™€ 같이 abcλ₯Ό μƒμ†λ°›λŠ” μΆ”μƒν΄λž˜μŠ€μ— λ°μ½”λ ˆμ΄ν„° λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜κ³ , λ©”μ†Œλ“œμ— 주석 μ„€λͺ…을 달아 λ†“μœΌλ©΄ μžμ‹ ν΄λž˜μŠ€μ—μ„œ μžμ„Έν•œ κ΅¬ν˜„μ„ ν•˜κ²Œλ˜λŠ” 방식이닀. 

 

import random

class CraneMachine(RandomMachine):
    def __init__(self, items):
        self._randomizer = random.SystemRandom()
        self._items = []
        self.load(items)
        
    def load(self, items):
        self._items.extend(items)
        self._randomizer.shuffle(self._items)

    def pick(self):
        try:
            return self._items.pop()
        except IndexError:
            raise LookupError('Empty Crane Box')

    def __call__(self):
        return self.pick()

이와 같이 abcλ₯Ό μƒμ†λ°›μ•˜λ˜ RandomMachine 클래슀λ₯Ό μƒμ†λ°›λŠ” CraneMachine 을 μƒμ„±ν•œλ‹€. μž…λ ₯ν•œ μ•„μ΄ν…œ 리슀트 μ€‘μ—μ„œ 랜덀 뽑기λ₯Ό ν•˜λŠ” ν΄λž˜μŠ€μ΄λ‹€. RandomMachineμ—μ„œ κ΅¬ν˜„ν•΄λ†“μ•˜λ˜ 좔상 λ©”μ†Œλ“œ load, pick ν•¨μˆ˜λŠ” ν•„μˆ˜λ‘œ κ΅¬ν˜„ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€. 

 

 

* μ„œλΈŒ 클래슀 확인 

print('EX5-1 - ', issubclass(RandomMachine, CraneMachine))
print('EX5-2 - ', issubclass(CraneMachine, RandomMachine))

 EX5-1 -  False 
 EX5-2 -  True 

issubclassλ₯Ό μ‚¬μš©ν•˜μ—¬ μ„œλΈŒν΄λž˜μŠ€μΈμ§€ 확인 ν•΄λ³Έλ‹€. issubclass(RandomMachine, CraneMachine)은 RandomMachine이 CraneMachine의 μ„œλΈŒν΄λž˜μŠ€λƒ? λΌλŠ” λœ»μ΄λ‹€. 

 

 

* 상속 ꡬ쑰 확인 

print('EX5-3 - ', CraneMachine.__mro__)  # 가계도λ₯Ό 보여쀀닀. 상속을 받은 μˆœμ„œλ₯Ό λ³΄μ—¬μ€Œ

 EX5-3 -  (<class '__main__.CraneMachine'>, <class '__main__.RandomMachine'>, <class 'abc.ABC'>, <class 'object'>) 

 

 

* 객체 생성

cm = CraneMachine(range(1, 100)) # 좔상 λ©”μ†Œλ“œ κ΅¬ν˜„ μ•ˆν•˜λ©΄ μ—λŸ¬

Sequenceλ₯Ό μƒμ†ν–ˆμ„ λ•Œ __getitem__, __len__ λ©”μ†Œλ“œκ°€ ν•„μˆ˜μ˜€λ‹€λ©΄, abcλ₯Ό 상속할 λ•ŒλŠ” 좔상 λ©”μ†Œλ“œλ₯Ό ν•„μˆ˜λ‘œ κ΅¬ν˜„ν•΄ μ£Όμ–΄μ•Ό ν•œλ‹€λŠ” κ°•μ œμ„±μ„ λˆλ‹€. 

 

print('EX5-4 - ', cm._items)
print('EX5-5 - ', cm.pick())
print('EX5-6 - ', cm())
print('EX5-7 - ', cm.inspect()) # --> λΆ€λͺ¨μ˜ λ©”μ†Œλ“œκ°€ μ‹€ν–‰λœλ‹€.

 EX5-4 -  [53, 83, 95, 24, 97, 2, 43, 89, 85, 3, 59, 15, 78, 12, 46, 11, 29, 72, 6, 60, 41, 51, 1, 67, 10, 88, 5, 62, 33, 18, 55, 61, 13, 63, 90, 81, 32, 65, 86, 75, 94, 71, 93, 70, 26, 54, 31, 20, 91, 35, 34, 68, 57, 42, 23, 8, 77, 69, 36, 28, 99, 17, 98, 56, 44, 22, 14, 27, 30, 48, 37, 80, 87, 52, 49, 50, 40, 74, 25, 47, 96, 9, 45, 73, 4, 16, 21, 7, 82, 39, 58, 66, 84, 19, 79, 76, 38, 64, 92] 
 EX5-5 -  92 
 EX5-6 -  64 
 EX5-7 -  (38,) 

inspectλ©”μ†Œλ“œλŠ” μžμ‹ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ν•΄μ£Όμ§€ μ•Šμ•„λ„ λΆ€λͺ¨μ˜ 클래슀의 λ©”μ†Œλ“œκ°€ μ‹€ν–‰λœλ‹€. 

 

 

 

 

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리)

 

<이전 κΈ€>

https://silvercoding.tistory.com/26

 

[python 심화] 9. λ³€μˆ˜ λ²”μœ„, Closure, Decorator

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리) <이전 κΈ€> https://silvercoding.tistory.com/25 이번 ν¬μŠ€νŠΈμ—μ„œλŠ” λ°μ½”λ ˆμ΄ν„°λ₯Ό μ•Œμ•„λ³Ό 것이닀. λ°μ½”λ ˆμ΄ν„°λŠ” μ–΄λ ΅λ‹€κ³  λŠλΌλŠ” 것이 λ‹Ήμ—°ν•˜λ‹€. λ°μ½”λ ˆμ΄ν„°

silvercoding.tistory.com

 

 

- 얕은 볡사 & is  vs  __eq__ (==) 

x = {'name': 'Kim','age': 33, 'city' : 'Seoul'}
y = x  # ---> 얕은 볡사

μš°μ„  x에 λ”•μ…”λ„ˆλ¦¬λ₯Ό μ €μž₯ν•œλ‹€. κ·Έλ‹€μŒ λ‹¨μˆœν•œ 볡사λ₯Ό ν•œλ‹€. 

print('EX2-1', id(x), id(y))  
print('EX2-2 - ', x == y)
print('EX2-3 - ', x is y)
print('EX2-4 - ', x, y)

 EX2-1 2324412065760 2324412065760 

μš°μ„  id 값을 좜λ ₯ν•΄λ³΄λ‹ˆ 두 값이 μ™„μ „νžˆ κ°™μ•˜λ‹€. 

 EX2-2 -  True 

 EX2-3 -  True 

2-2와 2-3은 μ§κ΄€μ μœΌλ‘œ 봐도 x와 yκ°€ 같은지λ₯Ό λ¬Όμ–΄λ³΄λŠ” μ½”λ“œμΈ 것 κ°™λ‹€. ν•˜μ§€λ§Œ λ‹€λ₯Έ μ’…λ₯˜μ˜ 확인법이닀. __eq__ (==) 와 같은 κ²½μš°λŠ” x와 y의 값이 같은지λ₯Ό ν™•μΈν•˜λŠ” 것이고 , isλŠ” x와 y의 id값이 같은지λ₯Ό ν™•μΈν•˜λŠ” 것이닀. 

 

** 정리 

==(__eq__) : 값을 비ꡐ  vs  is : 객체 μ£Όμ†Œ (정체성) 비ꡐ

 

 EX2-4 -  {'name': 'Kim', 'age': 33, 'city': 'Seoul'} {'name': 'Kim', 'age': 33, 'city': 'Seoul'} 

μœ„ μ˜ˆμ œμ—μ„œλŠ” κ°’, id λͺ¨λ‘ κ°™λ‹€. x와 yλ₯Ό 좜λ ₯ν•˜λ©΄ λ‹Ήμ—°ν•œ 결과둜 같은 λ”•μ…”λ„ˆλ¦¬κ°€ λ‚˜μ˜€λŠ” 것을 λ³Ό 수 μžˆλ‹€. 

 

x의 값을 μˆ˜μ •ν•˜κ±°λ‚˜ μΆ”κ°€ν•˜λ©΄ y도 λ°”λ€”κΉŒ? id값이 κ°™μœΌλ―€λ‘œ λ°”λ€” κ²ƒμœΌλ‘œ μΆ”μ •ν•  수 μžˆλ‹€. 

x['class'] = 10 
print('EX2-5 - ', x, y)

 

 EX2-5 -  {'name': 'Kim', 'age': 33, 'city': 'Seoul', 'class': 10} {'name': 'Kim', 'age': 33, 'city': 'Seoul', 'class': 10} 

x에 값을 μΆ”κ°€ν–ˆλ”λ‹ˆ y도 λ˜‘κ°™μ΄ μΆ”κ°€λ˜λŠ” 것을 μ•Œ 수 μžˆλ‹€. 

 

z = {'name': 'Kim','age': 33, 'city' : 'Seoul', 'class' : 10}

μƒˆ λ”•μ…”λ„ˆλ¦¬ 객체λ₯Ό λ§Œλ“€μ–΄ λ³Έλ‹€. 값은 x와 같도둝! 

print('EX2-6 - ', x, z)
print('EX2-7 - ', x is z)  # 같은 객체냐 
print('EX2-8 - ', x is not z)  
print('EX2-9 - ', x == z)  # 값이 같냐

 EX2-6 -  {'name': 'Kim', 'age': 33, 'city': 'Seoul', 'class': 10} {'name': 'Kim', 'age': 33, 'city': 'Seoul', 'class': 10} 
 EX2-7 -  False 
 EX2-8 -  True 
 EX2-9 -  True 

x와 zλ₯Ό 비ꡐ해 보면 id값은 λ‹€λ₯΄κ³ , κ°’λ§Œ κ°™λ‹€κ³  λ‚˜μ˜€λŠ” 것을 λ³Ό 수 μžˆλ‹€. 이 κ²½μš°μ—λŠ” x의 값을 λ³€κ²½ν•˜μ—¬λ„ z의 값은 λ³€ν•˜μ§€ μ•Šμ„ 것이닀. (λ‹Ήμ—°ν•œ μ†Œλ¦¬) 

 

 

*** cf ) νŠœν”Œ (λΆˆλ³€ν˜•) 비ꡐ 

tuple1 = (10, 15, [100, 1000])
tuple2 = (10, 15, [100, 1000])

print('EX3-1 - ', id(tuple1), id(tuple2))
print('EX3-2 - ', tuple1 is tuple2)
print('EX3-3 - ', tuple1 == tuple2)
print('EX3-4 - ', tuple1.__eq__(tuple2))

 EX3-1 -  2324415315832 2324415315544 
 EX3-2 -  False 
 EX3-3 -  True 
 EX3-4 -  True 

 

 

 

 

- Copy & DeepCopy (얕은 볡사 , κΉŠμ€ 볡사) 

tl1 = [10, [100, 105], (5, 10, 15)]
tl2 = tl1
tl3 = list(tl1)

리슀트 μ•ˆμ— 숫자, 리슀트, νŠœν”Œμ„ 각각 넣은 ν›„, tl2μ—λŠ” 얕은 볡사λ₯Ό , tl3μ—λŠ” list의 μΈμžμ— λ„£μ–΄ μƒˆ 객체λ₯Ό 생성해 μ€€λ‹€. 

print('EX4-1 - ', tl1 == tl2)
print('EX4-2 - ', tl1 is tl2)
print('EX4-3 - ', tl1 == tl3)
print('EX4-4 - ', tl1 is tl3)

 EX4-1 -  True 
 EX4-2 -  True 
 EX4-3 -  True 
 EX4-4 -  False 

4-3κ³Ό 4-4와 같은 κ²½μš°λŠ” 값은 κ°™μ§€λ§Œ, κ°μ²΄λŠ” λ‹€λ₯΄λ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€. 

 

 

tl1.append(1000)
tl1[1].remove(105)

tl1에 1000을 μΆ”κ°€ν•˜κ³ , 1번째 λ¦¬μŠ€νŠΈμ—μ„œ 105λ₯Ό μ œκ±°ν•˜λ©΄ μ–΄λ–»κ²Œ 될까 ! 

print('EX4-5 - ', tl1)
print('EX4-6 - ', tl2)
print('EX4-7 - ', tl3)

 EX4-5 -  [10, [100], (5, 10, 15), 1000] 
 EX4-6 -  [10, [100], (5, 10, 15), 1000] 
 EX4-7 -  [10, [100], (5, 10, 15)] 

tl2λŠ” 같은 객체둜 λ³΅μ‚¬λ˜μ–΄ 있기 λ•Œλ¬Έμ— tl1κ³Ό 같은 것을 λ³Ό 수 μžˆλ‹€. 그런데 tl3λŠ” 반만 λ˜‘κ°™λ‹€! μ™œ 그럴까? 

print(id(tl1[1])) # tl1κ³Ό tl3의 idλŠ” λ‹€λ₯΄μ§€λ§Œ μ•ˆμ— μžˆλŠ” 리슀트의 id값은 κ°™λ‹€. ! 
print(id(tl3[1]))

 2324415643528 
 2324415643528 

μ•„ . tl1κ³Ό tl3 자체 객체의 id값은 λ‹¬λžμ§€λ§Œ, κ·Έ μ•ˆμ— μžˆλŠ” 1번째 리슀트의 id값은 κ°™μ•˜λ‹€. 점점 이 λ°©λ²•μœΌλ‘œ ν•˜λŠ” λ³΅μ‚¬μ˜ ν—ˆμ μ΄ 보이기 μ‹œμž‘ν•œλ‹€. 

 

tl1[1] += [110, 120]
tl1[2] += (110, 120)

tl1의 λ¦¬μŠ€νŠΈμ™€ νŠœν”Œμ— 각각 값을 μΆ”κ°€ν•΄μ€€λ‹€. 

print('EX4-8 - ', tl1)
print('EX4-9 - ', tl2) # νŠœν”Œ 재 ν• λ‹Ή (깩체 μƒˆλ‘œ 생성) ---> 데이터가 ν˜„μ €νžˆ λ§Žμ„ λ–ˆ 주의 ν•΄μ•Ό ν•œλ‹€. 객체λ₯Ό μƒˆλ‘œ μƒμ„±ν•œλ‹€λŠ” 것은 데이터 손싀이 μžˆμ„ μˆ˜λ„ 있고 , λ©”λͺ¨λ¦¬λ₯Ό 더 차지할 μˆ˜λ„ 있게 되기 λ•Œλ¬Έ !
print('EX4-10 - ', tl3)

 EX4-8 -  [10, [100, 110, 120], (5, 10, 15, 110, 120), 1000] 
 EX4-9 -  [10, [100, 110, 120], (5, 10, 15, 110, 120), 1000] 
 EX4-10 -  [10, [100, 110, 120], (5, 10, 15)] 

μš°μ„  tl1, tl2λŠ” μ—¬κΈ°μ„œλ„ λ˜‘κ°™μ΄ 움직인 λ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€. 그런데 tl3μ—μ„œλŠ” 쑰금 μ΄μƒν•œ ν˜„μƒμ΄ 일어났닀. λ¦¬μŠ€νŠΈλŠ” 값이 μΆ”κ°€λ˜μ—ˆμ§€λ§Œ , νŠœν”Œμ€ 값이 μΆ”κ°€λ˜μ§€ μ•Šμ•˜λ‹€. 닡은 μ½”λ“œ 주석에 μ¨μžˆλ“―μ΄, νŠœν”Œμ€ 객체λ₯Ό μƒˆλ‘œ μƒμ„±ν•˜μ—¬ 재 할당이 되기 λ•Œλ¬ΈμΈλ°, 이해λ₯Ό μœ„ν•˜μ—¬ id값을 좜λ ₯ν•΄λ³΄μ•˜λ‹€. 

 

# 리슀트, νŠœν”Œμ— κ°’ μΆ”κ°€ μ „ 
print(id(tl1[2]))
print(id(tl2[2]))
print(id(tl3[2]))

...

# 리슀트, νŠœν”Œμ— κ°’ μΆ”κ°€ ν›„
print(id(tl1[2]))
print(id(tl2[2]))
print(id(tl3[2]))

 1367137568664 
 1367137568664 
 1367137568664 

 

 1367137218056 
 1367137218056 
 1367137568664 

리슀트처럼 tl1, tl3의 νŠœν”Œ id값은 κ°™μ•˜λ‹€. νŠœν”Œμ—μ„  이게 μ΄μŠˆκ°€ λ˜λŠ” 것이닀! tl1[2] += (110, 120) <--- 이 μ½”λ“œκ°€ μ‹€ν–‰λ˜λ©΄ νŠœν”Œμ΄ μž¬ν• λ‹Ήλ˜μ–΄ μƒˆ 객체가 μƒμ„±λœλ‹€. κ·Έλž˜μ„œ id값을 보면 이 μ½”λ“œ μ „κ³Ό ν›„μ˜ tl1, tl2 id값이 달라진 것을 λ³Ό 수 μžˆλ‹€. κ·Έλž˜μ„œ μ „κ³Ό 같은 id값을 가진 tl3의 νŠœν”Œμ€ λ³€ν™”ν•˜μ§€ μ•ŠλŠ” 것이닀. 

 

 

 

 

*** copy & Deep copy (κΉŠμ€ 볡사) μ‹€μŠ΅ν•΄λ³΄κΈ° 

(ex) μž₯λ°”κ΅¬λ‹ˆ 클래슀 

class Basket:
    def __init__(self, products=None):
        if products is None:
            self._products = []
        else:
            self._products = list(products)  # μƒˆλ‘œμš΄ 객체 생성

    def put_prod(self, prod_name):
        self._products.append(prod_name)

    def del_prod(self, prod_name):
        self._products.remove(prod_name)

_products에 물건을 λ‹΄κ³ , put_prod λ©”μ†Œλ“œλ‘œ 물건 μΆ”κ°€ , del_prod λ©”μ†Œλ“œλ‘œ 물건 μ‚­μ œλ₯Ό ν•˜λŠ” 클래슀 생성! 

import copy

basket1 = Basket(['Apple', 'Bag', 'TV', 'Snack', 'Water'])
basket2 = copy.copy(basket1)  # 얕은 볡사 
basket3 = copy.deepcopy(basket1)  # κΉŠμ€ 볡사 ---> 객체 μ•ˆμ— μžˆλŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜κΉŒμ§€ μ°Έμ‘°

copyλ₯Ό importν•˜μ—¬ 얕은 볡사(copy.copy) 와 κΉŠμ€ 볡사(copy.deepcopy) λ₯Ό ν•΄λ³Έλ‹€. 

print('EX5-1 - ', id(basket1), id(basket2), id(basket3))
print('EX5-2 - ', id(basket1._products), id(basket2._products), id(basket3._products))

 EX5-1 -  1367137770520 1367137770464 1367137771304 
 EX5-2 -  1367137799240 1367137799240 1367137626888 

copyλ₯Ό μ‚¬μš©ν•˜λ©΄ 객체 μžμ²΄λŠ” λͺ¨λ‘ λ‹€λ₯΄κ²Œ λ‚˜μ˜€λŠ” 것을 λ³Ό 수 μžˆλ‹€. EX5-2μ—μ„œ 얕은 볡사와 κΉŠμ€λ³΅μ‚¬μ˜ 차이점이 보인닀. deepcopyλŠ” 객체 μ•ˆμ— μžˆλŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜κΉŒμ§€ μ°Έμ‘°λ₯Ό ν•˜κΈ° λ•Œλ¬Έμ— λ³€μˆ˜μ˜ κ°μ²΄κΉŒμ§€ id의 값이 λ‹€λ₯΄λ‹€! 

 

basket1.put_prod('Orange')
basket2.del_prod('Snack')

basket1에 Orangeλ₯Ό λ„£κ³ , Snack을 μ‚­μ œν•˜λ©΄ μ–΄λ–»κ²Œ λ³€ν•˜λŠ”μ§€ 확인해 보자! 

# λΉ…λ°μ΄ν„°λ‚˜, μ›Ήκ°œλ°œν•  λ–„ μ£Όμ˜ν•΄μ•Ό ν•œλ‹€. 
print('EX5-3 - ', basket1._products)
print('EX5-4 - ', basket2._products)  
print('EX5-5 - ', basket3._products)

 EX5-3 -  ['Apple', 'Bag', 'TV', 'Water', 'Orange'] 
 EX5-4 -  ['Apple', 'Bag', 'TV', 'Water', 'Orange'] 
 EX5-5 -  ['Apple', 'Bag', 'TV', 'Snack', 'Water'] 

μ΄λ ‡κ²Œ basket1κ³Ό basket2λŠ” μ„œλ‘œ 영ν–₯을 λ°›λŠ”λ‹€. κΉŠμ€λ³΅μ‚¬λ₯Ό ν•œ basket3λŠ” 영ν–₯을 받지 μ•ŠλŠ”λ‹€. 

μ΄λŠ” 빅데이터 λ˜λŠ” μ›Ήκ°œλ°œμ„ ν•  λ•Œ μ£Όμ˜ν•΄μ•Ό ν•œλ‹€. 예λ₯Ό λ“€μ–΄ 빅데이터 뢄석을 ν•  λ•Œ 원본은 μ†μƒμ‹œν‚€μ§€ μ•Šκ³  볡사λ₯Ό ν•˜μ—¬ μ „μ²˜λ¦¬λ₯Ό ν•  경우 얕은 볡사λ₯Ό ν•˜κ²Œ 되면 μƒκ°λ§Œ 해도 μ•„μ°”ν•˜λ‹€. 

 

 

 

- ν•¨μˆ˜ λ§€κ°œλ³€μˆ˜ 전달 주의 

def mul(x, y):
    x += y
    return x

x에 yλ₯Ό λ”ν•΄μ„œ x에 λ„£κ³ , xλ₯Ό returnν•΄μ£ΌλŠ” mul ν•¨μˆ˜ 생성 

x = 10 
y = 5

print('EX6-1 - ', mul(x, y), x, y)

 EX6-1 -  15 10 5 

ν•¨μˆ˜ μ•ˆμ˜ xκ°€ 15라고 ν•΄μ„œ μ „μ—­λ³€μˆ˜ x의 값이 λ³€κ²½λ˜μ§€λŠ” μ•ŠλŠ”λ‹€. 

 

 

* κ°€λ³€ν˜• a -> 원본 데이터 λ³€κ²½/ ν•¨μˆ˜μ— 전달할 λ•Œ μ›λ³Έμ˜ μ£Όμ†ŒκΉŒμ§€ λ„˜κΉ€

a = [10, 100]
b = [5, 10]

print('Ex6-2 - ', mul(a, b), a, b)  # ---> ν™•μž₯! ! ! ! !

 Ex6-2 -  [10, 100, 5, 10] [10, 100, 5, 10] [5, 10] 

ν•˜μ§€λ§Œ κ°€λ³€ν˜•μΈ 리슀트 νƒ€μž…μ˜ aλ₯Ό mul에 λ„£μœΌλ©΄ μ „μ—­λ³€μˆ˜μΈ a의 κ°’κΉŒμ§€ 변해버린닀. 즉 원본데이터가 λ³€κ²½λ˜λŠ” 것이닀. ν•¨μˆ˜μ— 이 데이터λ₯Ό 전달할 λ•Œ μ›λ³Έμ˜ μ£Όμ†ŒκΉŒμ§€ λ„˜κΈ°κΈ° λ•Œλ¬Έμ΄λ‹€. 

 

 

* λΆˆλ³€ν˜• c ---> 원본 데이터 λ³€κ²½ μ•ˆλ¨

c = (10, 100)
d = (5, 10)
print('Ex6-2 - ', mul(c, d), c, d)

λΆˆλ³€ν˜•μΈ νŠœν”Œνƒ€μž…μ˜ c같은 κ²½μš°μ—λŠ” 원본 λ°μ΄ν„°μ˜ 변경이 λ˜μ§€ μ•ŠλŠ”λ‹€. μœ„μ—μ„œ 배웠듯이 νŠœν”Œμ˜ λ‚΄μš©μ΄ 갱신될 λ•ŒλŠ” μƒˆλ‘œμš΄ μ£Όμ†Œμ— 할당이 되기 λ•Œλ¬Έμ΄λ‹€. 

 

 

 

 

- 파이썬 λΆˆλ³€ν˜• μ˜ˆμ™Έ 

: str, bytes, frozenset, Tuple ---> 사본 생성 X ---> μ°Έμ‘° λ°˜ν™˜ (같은 값이면 id 도 κ°™λ‹€) 

tt1 = (1, 2, 3, 4, 5)
tt2 = tuple(tt1)
tt3 = tt1[:]

μ΄λ²ˆμ—” νŠœν”Œμ„ 각각 λ‹€λ₯Έ λ°©λ²•μœΌλ‘œ λ³΅μ‚¬ν•˜μ—¬ tt2와 tt3λ₯Ό μƒμ„±ν•˜μ˜€λ‹€. 

print('EX7-1 - ', tt1 is tt2, id(tt1), id(tt2))
print('EX7-2 - ', tt1 is tt3, id(tt1), id(tt3))

 EX7-1 -  True 1367134857000 1367134857000 
 EX7-2 -  True 1367134857000 1367134857000 

λ¦¬μŠ€νŠΈλŠ” μœ„μ™€ 같은 λ°©λ²•μœΌλ‘œ 객체λ₯Ό μƒμ„±ν•˜λ©΄ μƒˆλ‘œμš΄ μ£Όμ†Œκ°€ λΆ€μ—¬λμ—ˆλ‹€. νŠœν”Œμ€ λΆˆλ³€ν˜•μ΄λ―€λ‘œ 같은 값이면 idλŠ” κ°™λ‹€. λ”°λΌμ„œ λͺ¨λ“  id값이 κ°™κ²Œ λ‚˜μ™”λ‹€. νŠœν”Œμ€ λΆˆλ³€ν˜•μ΄κΈ° λ•Œλ¬Έμ— νŠœν”Œμ— νŠœν”Œμ„ 더할 λ•Œ κΈ°μ‘΄ νŠœν”Œμ— 값이 μΆ”κ°€λ˜λŠ” κ°œλ…μ΄κΈ° λ³΄λ‹€λŠ” μƒˆλ‘œμš΄ νŠœν”Œ 객체가 λ§Œλ“€μ–΄μ§€λŠ” 것이라고 보면 λœλ‹€.  

 

tt4 = (10, 20, 30, 40, 50)
tt5 = (10, 20, 30, 40, 50)
ss1 = 'Apple'
ss2 = 'Apple'

νŠœν”Œκ³Ό λ˜λ‹€λ₯Έ λΆˆλ³€ν˜• str둜 검증을 해보고 λ§ˆμΉœλ‹€. 

print('EX7-3 - ', tt4 is tt5, tt4 == tt5, id(tt4), id(tt5))
print('EX7-4 - ', ss1 is ss2, ss1 == ss2, id(ss1), id(ss2))

 EX7-3 -  True True 1367137216648 1367137216648 
 EX7-4 -  True True 1367137769320 1367137769320 

값이 κ°™μœΌλ©΄ λ‹€λ₯Έ λ³€μˆ˜μ— λ”°λ‘œ 생성을 해도 같은 μ£Όμ†Œλ₯Ό κ°–κ³  μžˆλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€. 

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리)

 

<이전 κΈ€>

https://silvercoding.tistory.com/25

 

이번 ν¬μŠ€νŠΈμ—μ„œλŠ” λ°μ½”λ ˆμ΄ν„°λ₯Ό μ•Œμ•„λ³Ό 것이닀. λ°μ½”λ ˆμ΄ν„°λŠ” μ–΄λ ΅λ‹€κ³  λŠλΌλŠ” 것이 λ‹Ήμ—°ν•˜λ‹€. λ°μ½”λ ˆμ΄ν„°μ— λ“€μ–΄κ°€κΈ° μ „μ—λŠ” λ³€μˆ˜μ˜ λ²”μœ„μ™€ ν΄λ‘œμ € κ°œλ…μ„ μ•Œμ•„μ•Ό ν•˜λ―€λ‘œ 이 λ‘˜μ„ λ¨Όμ € μ‚΄νŽ΄λ³΄μž.

 

- 파이썬 λ³€μˆ˜ λ²”μœ„ 

*** μ „μ—­λ³€μˆ˜ vs μ§€μ—­λ³€μˆ˜ μ°Έκ³  

https://wikidocs.net/62

 

μœ„ν‚€λ…μŠ€

온라인 책을 μ œμž‘ κ³΅μœ ν•˜λŠ” ν”Œλž«νΌ μ„œλΉ„μŠ€

wikidocs.net

μ—¬κΈ° μ΄ν•΄ν•˜κΈ° μ‰½κ²Œ 정리가 λ˜μ–΄μžˆλ‹€! 

 

직접 μ‹€μŠ΅ν•΄λ³΄μž 

# 예제 1
def func_v1(a):
    print(a)
    print(b)


# 였λ₯˜
# func_v1(5)

 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 19, in <module>
    func_v1(5) 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 15, in func_v1       
    print(b) 
 NameError: name 'b' is not defined 

 

예제1κ³Ό 같은 ν•¨μˆ˜λ₯Ό μž‘μ„±ν•˜κ³ , ν˜ΈμΆœν•˜λ©΄ λ‹Ήμ—°ν•œ 결과둜 NameErrorκ°€ λ‚œλ‹€. bκ°€ μ •μ˜λ˜μ–΄ μžˆμ§€ μ•Šμ€λ° bλ₯Ό 좜λ ₯ν•˜λΌκ³  μž‘μ„±ν•˜μ˜€κΈ° λ•Œλ¬Έμ΄λ‹€. 

 

 

# 예제 2 
b = 10

def func_v2(a):
    print(a)
    print(b)

func_v2(5)

κ·Έλ ‡λ‹€λ©΄ μ΄λ ‡κ²Œ ν•¨μˆ˜ 밖에 bλ₯Ό μ„ μ–Έν•˜κ³  ν•¨μˆ˜ μ•ˆμ—μ„œ bλ₯Ό 좜λ ₯ν•˜λ©΄ μ–΄λ–»κ²Œ 될까? 

 5  
 10  

μœ„μ™€ 같이 좜λ ₯이 λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. μ΄λ•Œμ˜ bλ₯Ό μ „μ—­λ³€μˆ˜λΌκ³  ν•œλ‹€.

 

 

# 예제3 
b = 10

def func_v3(a):
    print(a)
    print(b)
    b = 5
    
func_v3(5)

μ΄λ ‡κ²Œ μž‘μ„±ν•œλ‹€λ©΄ μ–΄λ–»κ²Œ 될까? 

Traceback (most recent call last):
  File "c:/Users/sooki/Desktop/python_high/chapter04_02.py", line 42, in <module>      
    func_v3(5) 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 39, in func_v3       
    print(b) 
UnboundLocalError: local variable 'b' referenced before assignment

였! UnboundLocalError κ°€ λ‚œλ‹€. ν• λ‹Ήλ˜κΈ° 전에 μ§€μ—­λ³€μˆ˜ 'b'κ°€ μ°Έμ‘°λ˜μ—ˆλ‹€λŠ” 것이닀. 

 

ν•¨μˆ˜ 내에 bκ°€ μžˆλŠ” 건 체크가 λ˜μ—ˆλŠ”λ°, b에 값을 ν• λ‹Ήν•˜κΈ° 전에 bλ₯Ό 좜λ ₯ν–ˆκΈ° λ•Œλ¬Έμ— μ—λŸ¬κ°€ λ‚œλ‹€. 

같은 μ΄λ¦„μ˜ μ „μ—­λ³€μˆ˜μ™€ μ§€μ—­λ³€μˆ˜κ°€ 있으면 ν•¨μˆ˜ λ‚΄μ—μ„œλŠ” μ§€μ—­λ³€μˆ˜κ°€ μš°μ„ μ΄λ©°, λŸ°νƒ€μž„μ˜ 인터프리터가 bκ°€ μžˆλŠ” 것을 μ²΄ν¬ν–ˆμ§€λ§Œ, 할당은 μœ„μ—μ„œλΆ€ν„° μ•„λž˜λ‘œ 이루어지기 λ•Œλ¬Έμ΄λ‹€.

 

* 증λͺ…

from dis import dis

print('EX1-1 - ')
print(dis(func_v3))

EX1-1 -
 38           0 LOAD_GLOBAL              0 (print) 
              2 LOAD_FAST                0 (a) 
              4 CALL_FUNCTION            1 
              6 POP_TOP 

 39           8 LOAD_GLOBAL              0 (print) 
             10 LOAD_FAST                1 (b) 
             12 CALL_FUNCTION            1 
             14 POP_TOP 
 
 40          16 LOAD_CONST               1 (5) 
             18 STORE_FAST               1 (b)  
             20 LOAD_CONST               0 (None) 
             22 RETURN_VALUE 
 None 

 

 

 

- Closure (ν΄λ‘œμ €) 

1. λ°˜ν™˜λ˜λŠ” λ‚΄λΆ€ ν•¨μˆ˜μ— λŒ€ν•΄μ„œ μ„ μ–Έλœ μ—°κ²° 정보λ₯Ό 가지고 μ°Έμ‘°ν•˜λŠ” 방식 

2. λ°˜ν™˜ λ‹Ήμ‹œ ν•¨μˆ˜μ˜ μœ νš¨λ²”μœ„λ₯Ό λ²—μ–΄λ‚œ λ³€μˆ˜ λ˜λŠ” λ©”μ†Œλ“œμ— 직접 접근이 κ°€λŠ₯ 

 

κΈ€λ‘œ 읽으면 이해가 μ–΄λ €μš°λ‹ˆ 직접 μ‹€μŠ΅ν•΄λ³΄κΈ° . 

a = 10 

print('EX2-1 - ', a + 10)
print('EX2-2 - ', a + 100)
print('EX2-3 - ', sum(range(1, 51)))
print('EX2-4 - ', sum(range(51, 101)))

 EX2-1 -  20 
 EX2-2 -  110 
 EX2-3 -  1275 
 EX2-4 -  3775 

aλΌλŠ” λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κ³  , λ”°λ‘œ λ”°λ‘œ 10, 100을 λ”ν•˜κ³  좜λ ₯ν•˜λ©΄ λ‹Ήμ—°ν•œ 결과둜 20, 110이 λ‚˜μ˜¨λ‹€. 

μœ„μ˜ μ˜ˆμ œλ“€ 처럼 κ°œλ³„μ μΈ 계산이 μ΄λ£¨μ–΄μ§€κ²Œ λœλ‹€. 

 

이와 λ‹€λ₯΄κ²Œ κ²°κ³Όλ₯Ό λˆ„μ ν•  μˆ˜λŠ” μ—†μ„κΉŒ? 에 λŒ€ν•œ λ‹΅μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλŠ” 것이 ν΄λ‘œμ €μ΄λ‹€. 

 

 

 

Q) κ²°κ³Όλ₯Ό λˆ„μ ν•  μˆ˜λŠ” μ—†μ„κΉŒ ? 

A1) 클래슀 이용 

class Averager():
    def __init__(self):
        self._series = []

    def __call__(self, v):
        self._series.append(v)
        print('class >>> {} / {}'.format(self._series, len(self._series)))
        return sum(self._series) / len(self._series)

μš°μ„  Averager ν΄λž˜μŠ€λŠ” 숫자λ₯Ό λ„£μœΌλ©΄ λ¦¬μŠ€νŠΈμ— μΆ”κ°€ν•˜μ—¬ 평균을 κ΅¬ν•΄μ£ΌλŠ” ν΄λž˜μŠ€μ΄λ‹€. 

객체λ₯Ό μƒμ„±ν•˜λ©΄ _series 에 빈 리슀트λ₯Ό μƒμ„±ν•œλ‹€. 

μ €λ²ˆ κΈ€μ—μ„œ 배운 __call__ λ©”μ†Œλ“œλŠ” 객체λ₯Ό λ©”μ†Œλ“œ ν˜•νƒœλ‘œ ν˜ΈμΆœν•  수 μžˆλ„λ‘ ν•΄ μ£ΌλŠ” κ²ƒμ΄μ—ˆλ‹€. 

 

# μΈμŠ€ν„΄μŠ€ 생성 
avg_cls = Averager()

print('EX3-1 - ', avg_cls(15))
print('EX3-2 - ', avg_cls(35))
print('EX3-2 - ', avg_cls(40))

 class >>> [15] / 1 
 EX3-1 -  15.0 
 class >>> [15, 35] / 2 
 EX3-2 -  25.0 
 class >>> [15, 35, 40] / 3 
 EX3-2 -  30.0 

μ΄λ ‡κ²Œ λˆ„μ μœΌλ‘œ μ €μž₯ν•΄λ‘μ—ˆλ‹€κ°€ 평균을 ꡬ해쀀닀. 

 

 

 

A2) ν΄λ‘œμ € 이용 

μ΄λ²ˆμ—” ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•œλ‹€. ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•˜λ©΄ 

1. μ „μ—­λ³€μˆ˜ μ‚¬μš© κ°μ†Œ 

2. λ””μžμΈ νŒ¨ν„΄ 적용 

def closure_avg1():
    # Free Variable
    # ν΄λ‘œμ € μ˜μ—­
    series = []
    def averager(v):
        # 여기에 seriesκ°€ μ—†λŠ”λ° 계속 μ°Έμ‘°ν•˜κ³  있음 
        # series = [] 여기에 μ“΄λ‹€λ©΄ 계속 μ΄ˆκΈ°ν™”λœ ν›„ append됨 
        series.append(v)
        print('def1 >>> {} / {}'.format(series, len(series)))
        return sum(series) / len(series)
    return averager # ν•¨μˆ˜ 자체λ₯Ό 리턴 averager() 이게 μ•„λ‹˜

 

ν΄λ‘œμ € μ˜μ—­μ—μ„œ seriesλ₯Ό μ„ μ–Έν•œ 것 λΉΌκ³ λŠ” λ‹€λ₯Έ 게 없어보인닀. μ›λž˜ ν•¨μˆ˜μ•ˆμ—μ„œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” ν•¨μˆ˜ 리턴과 λ™μ‹œμ— μ΄ˆκΈ°ν™”λœλ‹€. ν•˜μ§€λ§Œ ν΄λ‘œμ € μ˜μ—­μ—μ„œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” μ΄ˆκΈ°ν™” λ˜μ§€ μ•Šμ•„ μ΄λŸ¬ν•œ λˆ„μ μœΌλ‘œ μΆ”κ°€λ˜λŠ” μ½”λ“œλ₯Ό 지 λ•Œ μ‚¬μš©ν•  수 μžˆλ‹€. 

avg_closuer1 = closure_avg1()

print('EX4-1 - ', avg_closuer1(15))
print('EX4-1 - ', avg_closuer1(35))
print('EX4-1 - ', avg_closuer1(40))

μ§€κΈˆλ³΄λ‹ˆ μ˜€νƒ€κ°€ 났닀 closuer 이라고 λ˜μ–΄μžˆλ‹€! 

def1 >>> [15] / 1
EX4-1 -  15.0
def1 >>> [15, 35] / 2
EX4-1 -  25.0
def1 >>> [15, 35, 40] / 3
EX4-1 -  30.0

κ²°κ³Όκ°€ 잘 λ‚˜μ˜€λŠ” 것을 λ³Ό 수 μžˆλ‹€. 

print('EX5-1 - ', dir(avg_closuer1))
print()
print('EX5-2 - ', dir(avg_closuer1.__code__))
print()
print('EX5-3- ', avg_closuer1.__code__.co_freevars)  # ν΄λ‘œμ €μ— μ ‘κ·Ό
print()
print('EX5-4 - ', dir(avg_closuer1.__closure__[0]))  
print()
print('EX5-5 - ', dir(avg_closuer1.__closure__[0].cell_contents[1]))

EX5-1 -  ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

__code__ 에 μ ‘κ·Ό
EX5-2 -  ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_kwonlyargcount', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
co_vars 에 μ ‘κ·Ό ---> ν΄λ‘œμ €μ— μ ‘κ·Ό 
EX5-3-  ('series',)
seriesκ°€ λ‚˜μ˜€λŠ” 것을 λ³Ό 수 μžˆλ‹€.
EX5-4 -  ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']

EX5-5 -  ['__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__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

 

 

 

*** 잘λͺ»λœ ν΄λ‘œμ € μ‚¬μš© 예 

def closure_avg2():
    # Free variable
    # ν΄λ‘œμ € μ˜μ—­ 
    cnt = 0 
    total = 0 
    
    def averager(v):
        cnt += 1
        total += v 
        print('def2 >>> {} / {}'.format(total, cnt))
        return total / cnt 
    return averager

 Traceback (most recent call last): 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 155, in <module>     
    print('EX5-5 - ', avg_closure2(15)) 
  File "c:/Users/./Desktop/python_high/chapter04_02.py", line 147, in averager     
    cnt += 1 
 UnboundLocalError: local variable 'cnt' referenced before assignment 

μ΄λ ‡κ²Œ μ‚¬μš©ν•˜λŠ” κ²½μš°μ—λŠ” UnboundLocalErrorκ°€ μ‹€ν–‰λœλ‹€. 

 

 

 

---> 해결방법 

def closure_avg2():
    # Free variable
    # ν΄λ‘œμ € μ˜μ—­ 
    cnt = 0 
    total = 0 
    def averager(v):
        nonlocal cnt, total  
        cnt += 1
        total += v 
        print('def2 >>> {} / {}'.format(total, cnt))
        return total / cnt 
    return averager

<nonlocal λ³€μˆ˜λͺ…> 을 λΆ™μ—¬μ£Όλ©΄ ν΄λ‘œμ € μ˜μ—­μ„ μ‚¬μš©ν•˜μ—¬ λ³€μˆ˜λ₯Ό 선언해쀄 수 μžˆλ‹€. 

avg_closure2 = closure_avg2()

print('EX5-5 - ', avg_closure2(15))
print('EX5-5 - ', avg_closure2(35))
print('EX5-5 - ', avg_closure2(40))

 def2 >>> 15 / 1 
 EX5-5 -  15.0 
 def2 >>> 50 / 2 
 EX5-5 -  25.0 
 def2 >>> 90 / 3 
 EX5-5 -  30.0 

그럼 κ²°κ³Ό 값이 잘 λ‚˜μ˜€λŠ” 것을 λ³Ό 수 μžˆλ‹€. 

 

 

- λ°μ½”λ ˆμ΄ν„° , Decorator 

μž₯점

1. μ€‘λ³΅μ œκ±°, μ½”λ“œ κ°„κ²° 

2. ν΄λ‘œμ €λ³΄λ‹€ 문법 κ°„κ²° 

3. μ‘°ν•©ν•΄μ„œ μ‚¬μš©ν•  λ•Œ 용이 

 

단점 

1. 디버깅이 어렀움 

2. μ—λŸ¬μ˜ λͺ¨ν˜Έν•¨ 

 

import time 

def perf_clock(func): 
    def perf_clocked(*args):
        # μ‹œμž‘ μ‹œκ°„ 
        st = time.perf_counter()
        result = func(*args)
        # μ’…λ£Œ μ‹œκ°„ 
        et = time.perf_counter() - st
        # ν•¨μˆ˜λͺ… 
        name = func.__name__ 
        # λ§€κ°œλ³€μˆ˜ 
        arg_str = ','.join(repr(arg) for arg in args)
        # 좜λ ₯ 
        print('Result : [%0.5fs] %s(%s) -> %r' % (et, name, arg_str, result))
        return result
    return perf_clocked

μš°μ„  perf_clock μ΄λΌλŠ” ν•¨μˆ˜λ₯Ό μƒμ„±ν•œλ‹€. ν•¨μˆ˜λ₯Ό μž…λ ₯ν•˜λ©΄ κ·Έ ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λŠ” 데 κ±Έλ¦¬λŠ” μ‹œκ°„κ³Ό κ·Έ ν•¨μˆ˜μ˜ λ°˜ν™˜ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•΄ μ£ΌλŠ” ν•¨μˆ˜μ΄λ‹€. 

 

 

* λ°μ½”λ ˆμ΄ν„° λ―Έμ‚¬μš© 

def time_func(seconds):
    time.sleep(seconds)


def sum_func(*numbers):
    return sum(numbers)


def fact_func(n):
    return 1 if n < 2 else n * fact_func(n-1)

총 3κ°€μ§€μ˜ ν•¨μˆ˜λ‘œ μ‹€ν—˜μ„ ν•΄λ³Έλ‹€. time_func : 2초 sleep , sum_fun : 숫자 ν•©ν•˜κΈ°, fact_func : νŒ©ν† λ¦¬μ–Ό 계산 

non_deco1 = perf_clock(time_func)
non_deco2 = perf_clock(sum_func)
non_deco3 = perf_clock(fact_func)

print('EX7-1 - ', non_deco1, non_deco1.__code__.co_freevars)
print('EX7-2 - ', non_deco2, non_deco2.__code__.co_freevars)
print('EX7-3 - ', non_deco3, non_deco3.__code__.co_freevars)

print('*' * 40, 'Called Non Deco -> time_func')
print('EX7-4 - ')
non_deco1(2)
print('EX7-5 - ')
non_deco2(100, 200, 300, 500)
print('EX7-6 - ')
non_deco3(100)

EX7-1 -  <function perf_clock.<locals>.perf_clocked at 0x0000029029B70EA0> ('func',)   
EX7-2 -  <function perf_clock.<locals>.perf_clocked at 0x0000029029B70F28> ('func',)   
EX7-3 -  <function perf_clock.<locals>.perf_clocked at 0x0000029029B74048> ('func',)   
**************************************** Called Non Deco -> time_func

 EX7-4 - Result : [2.00830s] time_func(2) -> None 
 EX7-5 -  Result : [0.00001s] sum_func(100,200,300,500) -> 1100 
 EX7-6 - Result : [0.00017s] fact_func(100) ->   93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 

perf_clock의 인자둜 각 ν•¨μˆ˜λ₯Ό λ„£μ–΄ λ³€μˆ˜λ₯Ό μ„ μ–Έν•΄μ€€λ‹€. κ·Έ λ‹€μŒ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ , μ›ν•˜λ˜ κ²°κ³Όκ°€ 잘 λ‚˜μ˜¨λ‹€! 

 

 

 

 

* λ°μ½”λ ˆμ΄ν„° μ‚¬μš© 

@perf_clock
def time_func(seconds):
    time.sleep(seconds)


@perf_clock
def sum_func(*numbers):
    return sum(numbers)


@perf_clock
def fact_func(n):
    return 1 if n < 2 else n * fact_func(n-1)

λ°μ½”λ ˆμ΄ν„°λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ ν•¨μˆ˜ μœ„μ— @perf_clock 을 μž‘μ„±ν•œλ‹€. 

print('*' * 40, 'Called Deco -> time_func')
print('EX7-7 - ')
time_func(2)

print('*' * 40, 'Called Deco -> sum_func')
print('EX7-7 - ')
sum_func(10, 20, 30, 40, 50)

print('*' * 40, 'Called Deco -> fact_func')
print('EX7-7 - ')
fact_func(5)

**************************************** Called Deco -> time_func 
EX7-7 -
Result : [2.01093s] time_func(2) -> None 
**************************************** Called Deco -> sum_func 
EX7-7 -
Result : [0.00002s] sum_func(10,20,30,40,50) -> 150 
**************************************** Called Deco -> fact_func 
EX7-7 -
Result : [0.00000s] fact_func(1) -> 1 
Result : [0.00026s] fact_func(2) -> 2 
Result : [0.00058s] fact_func(3) -> 6 
Result : [0.00087s] fact_func(4) -> 24 
Result : [0.00110s] fact_func(5) -> 120 

그럼 μ΄λ ‡κ²Œ λ³€μˆ˜λ₯Ό 생성해주지 μ•Šμ•„λ„ κ°„λ‹¨ν•˜κ²Œ κ²°κ³Όλ₯Ό 얻을 수 μžˆλ‹€. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리)

 

<이전 κΈ€>

https://silvercoding.tistory.com/24

 

[python 심화] 7. ν•΄μ‹œν…Œμ΄λΈ”(hashtable), Dictionary, Set 심화

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리) <이전 κΈ€> https://silvercoding.tistory.com/23 https://silvercoding.tistory.com/22 https://silvercoding.tistory.com/21 https://silvercoding.tistory.com/20..

silvercoding.tistory.com

 

 

 

μ˜ˆμ „ κΈ€μ—μ„œλ„ λ‹€λ£¨μ—ˆλ“―μ΄ 파이썬의 λͺ¨λ“  것은 객체 λΌλŠ” κ°œλ…μ€ μ•„μ£Ό μ€‘μš”ν•œ κ°œλ…μ΄μ—ˆλ‹€. 이λ₯Ό 톡해 ν•¨μˆ˜ λ˜ν•œ κ°μ²΄λΌλŠ” 것을 μ•Œ 수 μžˆλ‹€. 

 

μΌκΈ‰ν•¨μˆ˜(일급 객체) - 파이썬 ν•¨μˆ˜μ˜ νŠΉμ§• 

1. λŸ°νƒ€μž„ μ΄ˆκΈ°ν™” κ°€λŠ₯ 

2. λ³€μˆ˜μ— ν• λ‹Ή κ°€λŠ₯ 

3. ν•¨μˆ˜ μΈμˆ˜μ— 전달 κ°€λŠ₯ (ex) sorted(keys=len) --- ν•¨μˆ˜ μ•ˆμ— ν•¨μˆ˜ 

4. ν•¨μˆ˜ 결과둜 λ°˜ν™˜ κ°€λŠ₯ (ex) return function  

 

 

 

 

- νŒ©ν† λ¦¬μ–Ό ν•¨μˆ˜ κ΅¬ν˜„ 예제 

def factorial(n):
    print("run")
    '''Factorial Function -> n:int'''
    if n ==1: # n < 2 
        return 1 
    return n * factorial(n-1)
    
    
class A: 
    pass 

μœ„μ—μ„œ λ³΄μ•˜λ˜ μΌκΈ‰ν•¨μˆ˜μ˜ νŠΉμ§• 쀑 4λ²ˆμ„ μ‚¬μš©ν•˜μ˜€λ‹€. ν•¨μˆ˜μ˜ 결과둜 ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•΄μ„œ νŒ©ν† λ¦¬μ–Όμ„ κ΅¬ν˜„ν•œ 것이닀. 

 

Aν΄λž˜μŠ€λŠ” ν•¨μˆ˜μ™€ 비ꡐ해 보기 μœ„ν•΄μ„œ μƒμ„±ν•œ 것 . 

 

 

 

* μ‚¬μš©ν•΄λ³΄κΈ°

print('EX1-1 - ', factorial(5))
print('EX1-2 - ', factorial.__doc__)
print('EX1-3 - ', type(factorial), type(A))
print('EX1-4 - ', set(sorted(dir(factorial)))-set(sorted(dir(A)))) # ν΄λž˜μŠ€μ™€ λ‹€λ₯΄κ²Œ ν•¨μˆ˜κ°€ κ°–κ³ μžˆλŠ” λ©”μ†Œλ“œλ“€
print('EX1-5 - ', factorial.__name__) # ν•¨μˆ˜ 이름 
print('EX1-6 - ', factorial.__code__) # ν•¨μˆ˜ μ½”λ“œ μœ„μΉ˜ 

EX1-1 μ—μ„œ λ³Ό 수 μžˆλ“―μ΄ factorial(5) λ₯Ό ν•˜λ©΄ run이 5번 호좜 λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. 

 

 

 

* λ³€μˆ˜ ν• λ‹Ή / ν•¨μˆ˜ 인자 전달

val_func = factorial
print('EX2-1 - ', val_func)
print('EX2-2 - ', val_func(5))
print('EX2-3 - ', map(val_func, range(1, 6)))
print('EX2-4 - ', list(map(val_func, range(1, 6))))

μΌκΈ‰ν•¨μˆ˜μ˜ νŠΉμ§• 2번과 같이 λ³€μˆ˜μ— ν• λ‹Ήν•  수 μžˆλ‹€. λ³€μˆ˜μ— ν•¨μˆ˜λ₯Ό λ„£κ³ , κΈ°μ‘΄ λ§Œλ“€μ–΄ λ†“μ•˜λ˜ ν•¨μˆ˜μ™€ λ˜‘κ°™μ΄ μ‚¬μš©ν•΄ μ£Όλ©΄ λœλ‹€. EX2-3, 4 μ—μ„œλŠ” νŠΉμ§• 3번과 같이 mapν•¨μˆ˜μ˜ μΈμžμ— factorial ν•¨μˆ˜λ₯Ό λ„£μ–΄ μ‚¬μš©ν•œ 것이닀.

EX2-4λŠ” μœ„μ™€κ°™μ΄ 리슀트둜 κ²°κ³Ό 값을 λ³Ό 수 μžˆλ‹€. 

 

# ν•¨μˆ˜ 인수 전달 및 ν•¨μˆ˜λ‘œ κ²°κ³Ό λ°˜ν™˜ -> κ³ μœ„ ν•¨μˆ˜ (Higher-order Function)
print('EX3-1 - ', list(map(val_func, filter(lambda x: x%2, range(1, 6))))) # --> ν•¨μˆ˜ μ•ˆμ— ν•¨μˆ˜ 전달 
print('EX3-2 - ', [val_func(i) for i in range(1, 6) if i % 2])

EX2-4 μ—μ„œ 더 λ‚˜μ•„κ°€ 1-6 μ€‘μ—μ„œ ν™€μˆ˜μΈ μˆ«μžλ“€λ§Œ factorial을 μ μš©μ‹œν‚€λŠ” μ½”λ“œμ΄λ‹€. 

EX3-1κ³Ό EX3-2 λŠ” 같은 κ²°κ³Όκ°€ λ‚˜μ˜€λŠ” μ½”λ“œμ΄μ§€λ§Œ, EX3-2λŠ” list comprehension을 μ‚¬μš©ν•˜μ˜€κ³ , EX3-1은 ν•¨μˆ˜μ˜ 인수둜 ν•¨μˆ˜λ₯Ό μ „λ‹¬ν•œλ‹€λŠ” μ μ—μ„œ 차이가 μžˆλ‹€. 

 

 

 

 

- reduce 

from functools import reduce
import functools
from operator import add

print('EX3-3 - ', reduce(add, range(1, 11))) # λˆ„μ  
print('EX3-4 - ', sum(range(1, 11)))

1λΆ€ν„° 10κΉŒμ§€ λ”ν•˜λŠ” μ½”λ“œλ₯Ό μ§œμ•Όν•œλ‹€κ³  ν•˜λ©΄ EX3-4 처럼 sumν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μ§œλŠ” 것이 μΌλ°˜μ μ΄λ‹€. 이 방법 말고도 functools의 reduceλ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•  μˆ˜λ„ μžˆλ‹€. 1λΆ€ν„° 11κΉŒμ§€ μ°¨λ‘€λŒ€λ‘œ 더해가며 μ€„μ—¬λ‚˜κ°€λŠ” 방식이닀. 

 

 

* 읡λͺ…ν•¨μˆ˜ (lambda) 와 reduce 

*** 읡λͺ…ν•¨μˆ˜ (lambda) 

1. 가급적 주석 μ‚¬μš© (가독성이 떨어지기 λ•Œλ¬Έ) 

2. 가급적 ν•¨μˆ˜ μ‚¬μš© 

3. 일반 ν•¨μˆ˜ ν˜•νƒœλ‘œ λ¦¬νŒ©ν† λ§ ꢌμž₯ 

print('EX3-5 - ', reduce(lambda x, t: x + t, range(1, 11)))

μœ„μ—μ„œμ˜ addν•¨μˆ˜ λŒ€μ‹  lambdaν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€. 1 + 2 ---> 3 + 3 ---> 6 + 4 ---> 10 + 5 이런 μ‹μœΌλ‘œ 더해진 값에 λˆ„μ μœΌλ‘œ λ‹€μŒ 수λ₯Ό λ”ν•΄μ£ΌλŠ” 원리이닀. 

 

 

<lambda, map(), reduce(), filter() μ°Έκ³ >

https://wikidocs.net/64

 

μœ„ν‚€λ…μŠ€

온라인 책을 μ œμž‘ κ³΅μœ ν•˜λŠ” ν”Œλž«νΌ μ„œλΉ„μŠ€

wikidocs.net

어렀움을 λŠλ‚„ 땐 μ˜ˆμ‹œλ₯Ό 보고 였기! 

 

 

 

 

- Callable : 호좜 μ—°μ‚°μž 

* λ©”μ†Œλ“œ ν˜•νƒœλ‘œ 호좜 κ°€λŠ₯ν•œμ§€ 확인 

---- 둜또 좔첨 클래슀 예제 ----

* 클래슀 μ„ μ–Έ 

import random

class LottoGame:
    def __init__(self):
        self._balls = [n for n in range(1, 46)]

    def pick(self):
        random.shuffle(self._balls)
        return sorted([random.choice(self._balls) for n in range(6)])

μš°μ„  random을 import ν•΄μ€€λ‹€. 객체λ₯Ό 초기 μƒμ„±ν–ˆμ„ λ•Œ _ballsμ—λŠ” 1λΆ€ν„° 45κΉŒμ§€μ˜ 숫자λ₯Ό 리슀트λ₯Ό λ„£μ–΄μ€€λ‹€. 

pick ν•¨μˆ˜μ—μ„œλŠ” random.shuffle을 μ‚¬μš©ν•˜μ—¬ _ballsλ₯Ό μ„žμ–΄ μ€€λ‹€. κ·Έλ‹€μŒ 6개λ₯Ό 뽑아쀀닀. 

 

 

* 객체 생성 

game = LottoGame()

 

 

* λ‘œλ˜μΆ”μ²¨ μ‹€ν–‰ 

print('EX4-2 - ', game.pick())

 EX4-2 -  [1, 5, 14, 24, 30, 34] 

μ΄λ ‡κ²Œ 6κ°œκ°€ 잘 λ½‘νžˆλŠ” 것을 μ•Œ 수 μžˆλ‹€. 

 

--- callable μ‚¬μš© 

print('EX4-1 - ', callable(str), callable(list), callable(factorial), callable(3.14), callable(game))

μœ„μ—μ„œ λ§ν–ˆλ“―μ΄ callable을 μ‚¬μš©ν•˜μ—¬ λ©”μ†ŒνŠΈ ν˜•νƒœλ‘œ 호좜 κ°€λŠ₯ν•œμ§€ μ•Œ 수 μžˆλ‹€. 

 EX4-1 -  True True True False False 

str, list, factorial은 λͺ¨λ‘ λ©”μ†Œλ“œ ν˜•νƒœλ‘œ 호좜이 κ°€λŠ₯ν•˜μ§€λ§Œ, μ‹€μˆ˜μΈ 3.14 λ˜λŠ” 객체가 λ“€μ–΄κ°€ μžˆλŠ” λ³€μˆ˜μΈ game 같은 κ²½μš°λŠ” λ©”μ†Œλ“œ ν˜•νƒœλ‘œ 호좜이 λΆˆκ°€λŠ₯ ν•˜λ‹€. 3.14(), game() <--- 이와 같은 ν˜•νƒœλ‘œ μ‚¬μš©ν•  수 μ—†λ‹€λŠ” μ†Œλ¦¬μ΄λ‹€. 

 

 

ν•˜μ§€λ§Œ ν΄λž˜μŠ€μ—μ„œ __call__λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ game같은 객체가 λ‹΄κΈ΄ λ³€μˆ˜λŠ” λ©”μ†Œλ“œ ν˜•νƒœλ‘œ ν˜ΈμΆœμ„ κ°€λŠ₯ν•˜κ²Œ λ§Œλ“€ 수 μžˆλ‹€. 

 

--- __call__ λ©”μ†Œλ“œ μ‚¬μš©ν•˜κΈ° (맀우 μ€‘μš”ν•œ κ°œλ…μž„) 

 

 

class LottoGame:

    ...

    def __call__(self):
        return self.pick()

LottoGame ν΄λž˜μŠ€μ— __call__λ©”μ†Œλ“œλ₯Ό μΆ”κ°€ν•΄ μ€€λ‹€. self.pick을 return ν•΄μ£ΌλŠ” κ²ƒμœΌλ‘œ μž‘μ„±ν•˜μ˜€μœΌλ―€λ‘œ, game()을 ν˜ΈμΆœν•˜λ©΄ pick 이 싀행될 것이닀. 

 

*** μ‚¬μš©ν•΄λ³΄κΈ° 

print('EX4-3 - ', game())
print('EX4-4 - ', callable(game))

 EX4-3 -  [14, 18, 42, 44, 44, 45] 
 EX4-4 -  True 

 

 

 

 

 

-- λ§€κ°œλ³€μˆ˜ μž…λ ₯ (*args, **kwargs) 

def args_test(name, *contents, point=None, **attrs):
    return '<args_test> -> ({}) ({}) ({}) ({})'.format(name, contents, point, attrs)

λ³Ό λ•Œλ§ˆλ‹€ ν—·κ°ˆλ Έλ˜ λ³„ν‘œ! ν•¨μˆ˜μ˜ μΈμžμ— 별 ν•˜λ‚˜ (*) κ°€ λΆ™μœΌλ©΄ νŠœν”Œμ„ λ°›κ³ , 별 λ‘κ°œ (**) κ°€ λΆ™μœΌλ©΄ λ”•μ…”λ„ˆλ¦¬λ₯Ό λ°›λŠ”λ‹€. 

ν…ŒμŠ€νŠΈλ₯Ό ν•˜κΈ° μœ„ν•΄ 일반 λ³€μˆ˜ name, νŠœν”Œμ„ λ°›λŠ” contents, default 값이 μ •ν•΄μ Έ μžˆλŠ” point, λ”•μ…”λ„ˆλ¦¬λ₯Ό λ°›λŠ” attrs, 총 4개의 인자λ₯Ό λ°›λŠ” ν•¨μˆ˜ args_testλ₯Ό μƒμ„±ν•˜μ˜€λ‹€. 

 

print('EX5-1 - ', args_test('test1'))
print('EX5-2 - ', args_test('test1', 'test2'))
print('EX5-3 - ', args_test('test1', 'test2', 'test3', id='admin'))
print('EX5-4 - ', args_test('test1', 'test2', 'test3', id='admin', point=7))
print('EX5-4 - ', args_test('test1', 'test2', 'test3', id='admin', point=7, password='1234'))

* ν•˜λ‚˜μ”© ν’€μ–΄μ„œ 정리 

 EX5-1 -  <args_test> -> (test1) (()) (None) ({}) 

'test1' ν•˜λ‚˜λ₯Ό λ„£μ—ˆλ”λ‹ˆ name에 λ“€μ–΄ κ°”λ‹€. 

 EX5-2 -  <args_test> -> (test1) (('test2',)) (None) ({}) 

'test1', 'test2' λ₯Ό λ„£μ—ˆλ”λ‹ˆ name, contents νŠœν”Œμ— λ“€μ–΄κ°”λ‹€. (default값이 μžˆλŠ” pointλŠ” pointλ₯Ό λͺ…μ‹œν•΄ μ£Όμ–΄μ•Ό ν•˜λ©°, attr은 λ”•μ…”λ„ˆλ¦¬λ₯Ό λ°›μœΌλ―€λ‘œ key, value값을 적어주어야 ν•œλ‹€.)  

 EX5-3 -  <args_test> -> (test1) (('test2', 'test3')) (None) ({'id': 'admin'}) 

'test1', 'test2', 'test3' λ₯Ό μ—°μ†μ μœΌλ‘œ 적어 μ£Όμ—ˆλ”λ‹ˆ name에 test1, contents νŠœν”Œμ— test2, test3κ°€ λ“€μ–΄κ°„ 것을 λ³Ό 수 μžˆλ‹€. μ°¨λ‘€λŒ€λ‘œ 적더라도 pointμ—λŠ” 듀어가지 μ•ŠλŠ”λ‹€. key와 valueλ₯Ό λ„£μ–΄μ£Όλ‹ˆ attr λ”•μ…”λ„ˆλ¦¬μ— λ“€μ–΄κ°„ 것 λ˜ν•œ λ³Ό 수 μžˆλ‹€. 

 EX5-4 -  <args_test> -> (test1) (('test2', 'test3')) (7) ({'id': 'admin'}) 

μ΄λ²ˆμ—λŠ” pointλ₯Ό λͺ…μ‹œν•΄μ£Όμ–΄ 값을 λ„£μ—ˆλ”λ‹ˆ 잘 λ“€μ–΄ κ°€ μžˆλ‹€. 

 EX5-4 -  <args_test> -> (test1) (('test2', 'test3')) (7) ({'id': 'admin', 'password': '1234'}) 

μˆœμ„œμ™€ 상관 없이 key, value λ₯Ό λ„£μ–΄μ£Όλ©΄ λ”•μ…”λ„ˆλ¦¬μ— λ“€μ–΄ κ°€ μžˆλ‹€. 

 

 

 

- ν•¨μˆ˜ Signature

: ν•¨μˆ˜μ˜ μΈμžμ— λŒ€ν•œ 정보λ₯Ό ν‘œμ‹œν•΄μ€„ 수 μžˆλŠ” 클래슀 ν˜•νƒœμ˜ λ©”μ†Œλ“œ 

from inspect import signature

 

μš°μ„  inspect의 signatureλ₯Ό import ν•΄μ€€λ‹€. 

 

sg = signature(args_test)

print('EX6-1 - ', sg)
print('EX6-2 - ', sg.parameters)

 EX6-1 -  (name, *contents, point=None, **attrs) 
 EX6-2 -  OrderedDict([('name', <Parameter "name">), ('contents', <Parameter "*contents">), ('point', <Parameter "point=None">), ('attrs', <Parameter "**attrs">)]) 

μœ„μ™€ 같이 ν•¨μˆ˜μ˜ μΈμžμ— λŒ€ν•œ 정보λ₯Ό 확인할 수 μžˆλ‹€. 

 

* 인자의 λͺ¨λ“  정보 좜λ ₯해보기 

# λͺ¨λ“  정보 좜λ ₯ 

for name, param in sg.parameters.items():
    print('EX6-3 - ', name, param.kind, param.default)

 

 EX6-3 -  name  POSITIONAL_OR_KEYWORD  <class 'inspect._empty'> 
 EX6-3 -  contents  VAR_POSITIONAL  <class 'inspect._empty'> 
 EX6-3 -  point  KEYWORD_ONLY  None 
 EX6-3 -  attrs  VAR_KEYWORD  <class 'inspect._empty'> 

 

 

 

 

- partial 

1. 주둜 νŠΉμ • 인수λ₯Ό κ³ μ •ν•œ ν›„ μ½œλ°±ν•¨μˆ˜μ— μ‚¬μš©

2. ν•˜λ‚˜ μ΄μƒμ˜ μΈμˆ˜κ°€ 이미 ν• λ‹Ήλœ ν•¨μˆ˜μ˜ μƒˆ 버전(μƒˆ λ²„μ „μ˜ ν•¨μˆ˜) λ°˜ν™˜ 

3. ν•¨μˆ˜μ˜ μƒˆ 객체 νƒ€μž…μ€ μ΄μ „ν•¨μˆ˜μ˜ 자체λ₯Ό κΈ°μˆ ν•˜κ³  있음 

 

κΈ€λ‘œ 읽으면 이해가 잘 가지 μ•Šμ„ 수 μžˆλ‹€. μ‚¬μš©ν•΄ 보자! 

from functools import partial

μš°μ„  functools의 partial을 import ν•΄μ€€λ‹€. 

 

 

*** cf ) mul ν•¨μˆ˜λŠ” μ™œ μžˆλ‚˜ 

from operator import mul 

print('EX7-1 - ', mul(10, 100))

μœ„ μ½”λ“œ 같은 κ²½μš°λŠ” 10 * 100 을 ν•˜λ©΄ 같은 κ²°κ³Όκ°€ λ‚˜μ˜¬ν…λ°, ꡳ이 mulκ³Ό 같은 ν•¨μˆ˜κ°€ μ‘΄μž¬ν•˜λŠ” μ΄μœ λŠ” 무엇인가. 

---> mulκ³Ό 같은 ν•¨μˆ˜λ₯Ό 인수둜 λ°›λŠ” κ²½μš°κ°€ 있기 λ•Œλ¬Έμ΄λ‹€. 

 

 

* 인수 κ³ μ • 

five = partial(mul, 5)

μ΄λ ‡κ²Œ partialν•¨μˆ˜μ˜ μΈμžμ— mulν•¨μˆ˜λ₯Ό λ„£μ–΄μ£ΌκΈ° μœ„ν•œ μš©λ„λ‘œ 쓰일 수 μžˆλ‹€. 

 

κ·Έλž˜μ„œ partial ν•¨μˆ˜κ°€ 무엇인가! 

인수λ₯Ό κ³ μ •μ‹œμΌœ λ†“λŠ” 역할을 ν•œλ‹€. partial(mul, 5) λŠ” mul(5) <--- 이 μƒνƒœλ‘œ 5λ₯Ό κ³ μ •μ‹œμΌœ λ†“κ² λ‹€λŠ” μ†Œλ¦¬μ΄λ‹€. 

 

 

* κ³ μ • μΆ”κ°€ 

six = partial(five, 6)

μ΄λ ‡κ²Œ ν•˜λ©΄ mul(5, 6) <--- 이 μƒνƒœλ‘œ 고정이 λ˜λŠ” 것이닀. 

 

* μ‚¬μš©

print('EX7-2 - ', five(100)) # ν•œκ°œλ§Œ 받을 수 있음 
# print(six(100)) # ---> 였λ₯˜ 남 . 아무것도 받을 수 μ—†μŒ 
print('EX7-3 - ', six())
print('EX7-4 - ', [five(i) for i in range(1, 11)])
print('EX7-5 - ', list(map(five, range(1, 11)))) 

EX7-4, 5 와 같이 5에 1~10의 숫자λ₯Ό κ³±ν•˜λŠ” 것과 λΉ„μŠ·ν•œ μƒν™©μ—μ„œ νŽΈλ¦¬ν•˜κ²Œ μ½”λ“œλ₯Ό 지 수 μžˆλ‹€. 

 

 

 

 

 

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리)

 

<이전 κΈ€>

https://silvercoding.tistory.com/23

 

[python 심화] 6. μžλ£Œν˜• (지λŠ₯ν˜• 리슀트, μ œλ„ˆλ ˆμ΄ν„°, κ°€λ³€λΆˆλ³€, μ •λ ¬)

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리) <이전 κΈ€> https://silvercoding.tistory.com/22 https://silvercoding.tistory.com/21 https://silvercoding.tistory.com/20 https://silvercoding.tistory.com/19..

silvercoding.tistory.com

 

 

- ν•΄μ‹œν…Œμ΄λΈ” (hashtable) 

ν•΄μ‹œν…Œμ΄λΈ”μ€ μž‘μ€ λ¦¬μ†ŒμŠ€λ‘œ λ§Žμ€ 데이터λ₯Ό 효율적으둜 κ΄€λ¦¬ν•œλ‹€. 

ν•΄μ‹œ ν…Œμ΄λΈ”μ€ key와 valueλ₯Ό 기반으둜 데이터λ₯Ό μ €μž₯ν•œλ‹€. 

 

*** Hash값을 확인 ν•¨μœΌλ‘œμ¨ 쀑볡이 ν—ˆμš©λ˜λŠ”μ§€ μ•ˆλ˜λŠ”μ§€ μ•Œ 수 있음 . 

# Hash κ°’ 확인  ---> 쀑볡이 ν—ˆμš©λ˜λŠ”μ§€ μ•ˆλ˜λŠ”μ§€ , 
t1 = (10, 20, (30, 40, 50))
t2 = (10, 20, [30, 40, 50])

print('EX1-2 - ', hash(t1))
# print('EX1-3 - ', hash(t2))  #---> λ¦¬μŠ€νŠΈκ°€ ν¬ν•¨λ˜μ–΄ 있기 λ•Œλ¬Έμ— 해쉬 μ“Έ 수 μ—†μŒ 

 

 

 

- 지λŠ₯ν˜• λ”•μ…”λ„ˆλ¦¬ (Comprehending Dict) 

(예제) κ΅­κ°€μ½”λ“œ csv 파일 -> tuple λ³€ν™˜ -> Dictionary λ³€ν™˜ 

(1) csv 파일 λΆˆλŸ¬μ™€μ„œ tuple둜 λ³€ν™˜ν•˜κΈ° ( 파일: 패캠 제곡

import csv
from os import kill
from typing import Counter 

# μ™ΈλΆ€ CSV TO List of tuple  
with open('./resources/test1.csv', 'r', encoding='UTF-8') as f:
    temp = csv.reader(f)
    # Header Skip
    next(temp)
    print()
    # λ³€ν™˜ 
    NA_CODES = [tuple(x) for x in temp]

print('EX2-1 - ')
print(NA_CODES)

λ‘μ€„κΉŒμ§€λ§Œ 캑쳐. μ΅œμ’…μ μœΌλ‘œ λ‚˜λΌ μ½”λ“œ νŠœν”Œμ΄ λ“€μ–΄κ°„ 리슀트λ₯Ό λ§Œλ“€μ—ˆλ‹€. 

 

 

(2) Dictionary 둜 λ³€ν™˜ (지λŠ₯ν˜• Dictionary μ‚¬μš©) 

n_code1 = {country: code for country, code in NA_CODES}
n_code2 = {country.upper() : code for country, code in NA_CODES}

n_code2λŠ” key값을 λŒ€λ¬Έμžλ‘œ λ°”κΏ”μ£ΌκΈ°κΉŒμ§€ ν•œ 것. 

 

 

 

 

 

- Dict Setdefault  

source = (('k1', 'val1'),
            ('k1', 'val2'),
            ('k2', 'val3'),
            ('k2', 'val4'),
            ('k2', 'val5'))

new_dict1 = {}
new_dict2 = {}

(1) No use setdefault 

for k, v in source:
    if k in new_dict1:
        new_dict1[k].append(v)
    else:
        new_dict1[k] = [v]

print('EX3-1 - ', new_dict1)

μ€‘λ³΅λ˜λŠ” keyκ°€ 있으면, λ¦¬μŠ€νŠΈμ— appendν•΄μ„œ dictλ₯Ό λ§Œλ“œλŠ” μ½”λ“œμ΄λ‹€. 

 

 

(2) Use setdefault ( μ΄κ²ƒμ˜ μ„±λŠ₯이 더 μ’‹λ‹€κ³  ν•œλ‹€. ) 

for k, v in source:
    new_dict2.setdefault(k, []).append(v)

print('EX3-2 - ', new_dict2)

setdefaultλ₯Ό μ‚¬μš©ν•˜λ©΄ if문을 μ‚¬μš©ν•˜μ§€ μ•Šκ³ λ„ μ΄λ ‡κ²Œ κ°„λ‹¨ν•˜κ²Œ ν•œμ€„λ‘œ κ΅¬ν˜„ν•  μˆ˜κ°€ μžˆλ‹€.

 

 

 

 

- μ‚¬μš©μž μ •μ˜ dict 상속 

class UserDict(dict):
    def __missing__(self, key):
        print('Called : __missing__')
        if isinstance(key, str):
            raise KeyError(key)
        return self[str(key)]

    def get(self, key, default=None):
        print("Called : __getitem__")
        try:
            return self[key]
        except KeyError:
            return default

    def __contains__(self, key):
        print("Called : __contains__")
        return key in self.keys() or str(key) in self.keys()

dictλ₯Ό μƒμ†λ°›μ•„μ„œ 클래슀λ₯Ό 생성할 수 μžˆλ‹€. 

 

user_dict1 = UserDict(one=1, two=2)
user_dict2 = UserDict({"one" : 1, "two" : 2})
user_dict3 = UserDict([('one', 1), ('two', 2)])

μ΄λ ‡κ²Œ λ”•μ…”λ„ˆλ¦¬ 객체λ₯Ό λ§Œλ“€μ–΄ 쀄 수 μžˆλ‹€. 

 

print('EX4-1 - ', user_dict1, user_dict2, user_dict3)
print('EX4-2 - ', user_dict2.get("two"))
print('EX4-3 - ', 'one' in user_dict3)
# print('EX4-4 - ', user_dict3['three'])
print('EX4-5 - ', user_dict3.get('three'))
print('EX4-6 - ', 'three' in user_dict3)

 

μ£Όμ„μ²˜λ¦¬ν•œ EX4-4 λ₯Ό μ‹€ν–‰ν•˜λ©΄ 

__missing__ 이 ν˜ΈμΆœλ˜λ©΄μ„œ μœ„μ—μ„œ μ •μ˜ν–ˆλ˜ ν‚€μ—λŸ¬κ°€ λ°œμƒν•˜κ²Œ λœλ‹€. 

 

 

 

 

- Immutable Dict 

from types import MappingProxyType

d = {'key1' : 'TEST1'}
# Read Only
d_frozen = MappingProxyType(d)

print('EX5-1 - ', d, id(d))
print('EX5-2 - ', d_frozen, id(d_frozen))
print('EX5-3 - ', d is d_frozen, d == d_frozen)

# d_frozen['key1'] = 'TEST2'  # ===> λ°”λ€Œμ§€ μ•ŠμŒ 

# 원본은 μˆ˜μ • κ°€λŠ₯ 
d['key2'] = 'TEST2'
print('EX5-4 - ', d)

 

d와 d_frozen 은 λ‹€λ₯Έ 객체 (λ‹€λ₯Έ id) 이고, κ°’(λ‚΄μš©)은 κ°™λ‹€κ³  λ‚˜μ˜€λŠ” 것을 λ³Ό 수 μžˆλ‹€. 

d_frozen을 μˆ˜μ •ν•˜λ €κ³  μ‹œλ„ν•˜λ©΄ μ—λŸ¬κ°€ λ‚œλ‹€. 읽기만 κ°€λŠ₯ν•œ 것이닀. 

원본인 dλŠ” μˆ˜μ •(μΆ”κ°€, μ‚­μ œ, λ³€κ²½)이 κ°€λŠ₯ν•˜λ‹€. 

 

 

 

- Set 

s1 = {'Apple', 'Orange', 'Apple', 'Orange', 'Kiwi'}
s2 = set(['Apple', 'Orange', 'Apple', 'Orange', 'Kiwi'])
s3 = {3}
s4 = set()  # Not {}
s5 = frozenset({'Apple', 'Orange', 'Apple', 'Orange', 'Kiwi'})

ν•œκ°€μ§€ μ£Όμ˜ν•  점은 λΉ„μ–΄μžˆλŠ” set객체λ₯Ό λ§Œλ“€ 땐 set() 을 μ‚¬μš©ν•˜μ—¬μ•Ό ν•œλ‹€. {} 으둜 μƒμ„±ν•˜λ©΄ dict 객체가 μƒμ„±λœλ‹€. 

# μΆ”κ°€ 
s1.add('Melon')

# μΆ”κ°€ λΆˆκ°€ 
# s5.add('Melon')

print('EX6-1 - ',  s1, type(s1))
print('EX6-2 - ',  s2, type(s2))
print('EX6-3 - ',  s3, type(s3))
print('EX6-4 - ',  s4, type(s4))
print('EX6-5 - ',  s5, type(s5))

Immutable Dict와 같이 frozenset으둜 μˆ˜μ •μ΄ λΆˆκ°€ν•˜κ²Œ λ§Œλ“€ 수 μžˆλ‹€. 

 

 

 

- μ„ μ–Έ μ΅œμ ν™” 

a = {5}  # ---> 이게 더 λΉ λ₯΄λ‹€. 
b = set([10])

 *** 증λͺ… 

from dis import dis 
print('EX6-5 - ')
print(dis('{10}'))

print('EX6-6 - ')
print(dis("set([10])"))

disλ₯Ό μ‚¬μš©ν•˜λ©΄ μ‹€ν–‰λ˜λŠ” μˆœμ„œλ₯Ό λ³Ό 수 μžˆλ‹€. 

{10} 의 μ ˆμ°¨κ°€ 더 적닀!

 

 

- 지λŠ₯ν˜• 집합 (Comprehending Set) 

from unicodedata import name

print('EX7-1 - ')
print({name(chr(i), "") for i in range(0, 256)})

λ”•μ…”λ„ˆλ¦¬μ™€ λΉ„μŠ·ν•˜κ²Œ for문을 {}μ•ˆμ— λ„£μ–΄μ£Όμ–΄ 지λŠ₯ν˜• 집합을 생성할 수 μžˆλ‹€. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리)

 

<이전 κΈ€>

https://silvercoding.tistory.com/22

 

[python 심화] 5. Special Method (Magic Method)

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리) <이전 κΈ€> https://silvercoding.tistory.com/21 https://silvercoding.tistory.com/20 https://silvercoding.tistory.com/19 https://silvercoding.tistory.com/18..

silvercoding.tistory.com

 

 

  • μ»¨ν…Œμ΄λ„ˆ (Container) : μ„œλ‘œ λ‹€λ₯Έ μžλ£Œν˜• 포함 κ°€λŠ₯ 

list, tuple, collections.deuqe  (ex) list --->[1, 3.0, 'hi']

  • Flat : ν•œκ°œμ˜ μžλ£Œν˜•λ§Œμ„ 포함 

str, bytes, bytearray, array.array, memoryview 

  • κ°€λ³€ 

list, bytearray, array.array, memoryview, deque

  • λΆˆλ³€ 

tuple, str, bytes 

 

 

λ‚˜λ¦„ νŒŒμ΄μ¬μ„ λ°°μš°λŠ” μ „κ³΅μžμ΄μ§€λ§Œ 심화과정 κ°•μ˜λ₯Ό λ“€μœΌλ©° 아직 λͺ¨λ₯΄λŠ” 게 정말 λ§Žμ€ 것 κ°™λ‹€λŠ” 생각이 λ“ λ‹€. 

μœ„μ˜ μžλ£Œν˜•λ“€λ§Œ 봐도! 

 

이번 ν¬μŠ€νŒ…μ—μ„œλŠ” 지λŠ₯ν˜• 리슀트, μ œλ„ˆλ ˆμ΄ν„°, νŠœν”Œ, λ”•μ…”λ„ˆλ¦¬μ˜ λ‚΄μš©μ„ 깊게 λ“€μ–΄κ°„λ‹€. 

 

 

- 지λŠ₯ν˜• 리슀트 (Comprehending Lists) 

*** None comprehending LIsts 

chars = '!@#$%^&*()_+'
codes1 = []

for s in chars:
    # μœ λ‹ˆμ½”λ“œ λ³€ν™˜
    codes1.append(ord(s))

 

지λŠ₯ν˜• 리슀트λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  일반적으둜 for문을 μ΄μš©ν•˜μ—¬ 리슀트 μ•ˆμ— 값을 λ„£μ–΄μ£ΌλŠ” μ˜ˆμ‹œμ΄λ‹€. 

 

*** Comprehending Lists 

μ—„μ²­ 큰 영ν–₯을 끼치게 λ˜λŠ” 것은 μ•„λ‹ˆμ§€λ§Œ, 빅데이터 뢄야와 같이 데이터가 ν˜„μ €ν•˜κ²Œ λ§Žμ•„μ§€λ©΄ 이 방법을 μ“°λŠ” 것이 μ„±λŠ₯, 속도 λ©΄μ—μ„œ 더 μœ λ¦¬ν•˜λ‹€κ³  ν•œλ‹€. 

codes2 = [ord(s) for i in chasrs]

리슀트 μ•ˆμ—μ„œ λ°”λ‘œ for문을 μ‚¬μš©ν•˜λŠ” 것이닀. 

 

 

*** Comprehending LIst + Map, Filter

이 방법 μ—­μ‹œ 속도가 μ•½κ°„ μš°μ„Έν•¨ . 

codes3 = [ord(s) for s in chars if ord(s) > 40]
codes4 = list(filter(lambda x : x > 40, map(ord, chars)))

결과적으둜 codes3와 codes4 리슀트 μ•ˆμ˜ 값듀을 κ°™λ‹€. codes3λŠ” forλ¬Έκ³Ό if문을 μ‚¬μš© , codes4λŠ” mapν•¨μˆ˜λ‘œ chars의 값듀에 ordν•¨μˆ˜λ₯Ό 적용 μ‹œν‚¨ ν›„ , lambda, filterλ₯Ό μ‚¬μš©ν•˜μ—¬ 40보닀 큰 κ°’λ“€λ§Œ λ‚˜μ˜€κ²Œ λ§Œλ“€μ–΄μ€€λ‹€.

 

 

*** 좜λ ₯해보기

print('EX1-1 - ', codes1)
print('EX1-2 - ', codes2)
print('EX1-3 - ', codes3)
print('EX1-4 - ', codes4)
print('EX1-5 - ', [chr(s) for s in codes1])
print('EX1-6 - ', [chr(s) for s in codes2])
print('EX1-7 - ', [chr(s) for s in codes3])
print('EX1-8 - ', [chr(s) for s in codes4])

EX1-5λΆ€ν„°λŠ” ord와 λ°˜λŒ€λ‘œ chr()λ₯Ό μ΄μš©ν•˜μ—¬ λ‹€μ‹œ λ°”κΎΈμ–΄μ„œ λ¦¬μŠ€νŠΈμ— λ„£μ–΄ μ£ΌλŠ” μ½”λ“œμ΄λ‹€. 

 

 

 

*** 리슀트 μ£Όμ˜ν•  점 

marks1 = [['~'] * 3 for n in range(3)]
marks2 = [['~'] * 3] * 3

print("EX4-1 - ", marks1)
print("EX4-2 - ", marks2)

이 두가지λ₯Ό 좜λ ₯ν•˜λ©΄ 

κ²°κ³ΌλŠ” κ°™λ‹€. 

 

--> κ°’ ν•˜λ‚˜ λ³€κ²½ 

marks1[0][1] = 'X'
marks2[0][1] = 'X'

print('EX4-3 - ', marks1)
print('EX4-3 - ', marks2)

λΆ„λͺ… ν˜•νƒœλŠ” κ°™μ•˜λŠ”λ°, 0번째 리슀트의 1번째 값을 λ³€κ²½ν•˜λŠ” μ½”λ“œλ₯Ό μž‘μ„±ν–ˆμ§€λ§Œ, λ‘λ²ˆμ§ΈλŠ” 0, 1, 2번째의 1번쨰 값이 λͺ¨λ‘ λ°”λ€Œμ—ˆλ‹€. 

 

---> 증λͺ… 

print('EX4-5 - ', [id(i) for i in marks1])
print('EX4-6 - ', [id(i) for i in marks2])

μœ„μ™€ 같이 marks1의 리슀트 듀은 λͺ¨λ‘ λ‹€λ₯Έ κ°μ²΄μ΄λ―€λ‘œ id값이 λ‹€λ₯΄μ§€λ§Œ, marks2의 λ¦¬μŠ€νŠΈλ“€μ€ 같은 리슀트λ₯Ό 3번 λ°˜λ³΅ν•΄ 놓은 것과 κ°™κΈ° λ•Œλ¬Έμ— id값이 λͺ¨λ‘ κ°™λ‹€. 같은 곳을 바라보고 있기 λ•Œλ¬Έμ— 0번쨰 리슀트의 κ°’λ§Œ λ°”κΎΈλ©΄ 1, 2번째 리슀트의 값도 ν•¨κ»˜ λ°”λ€ŒλŠ” 것이닀. 

 

데이터 뢄석을 ν•  λ•Œ 이런 μ‹€μˆ˜λ₯Ό ν•œλ‹€κ³  μƒκ°ν•˜λ©΄ λ”μ°ν•˜λ‹€!

 

 

 

- μ œλ„ˆλ ˆμ΄ν„° , Generator & Array 

(1) μ œλ„ˆλ ˆμ΄ν„°

μ œλ„ˆλ ˆμ΄ν„°λŠ” ν•œ λ²ˆμ— ν•œ 개의 ν•­λͺ©μ„ μƒμ„±ν•˜λ―€λ‘œ λ©”λͺ¨λ¦¬λ₯Ό μœ μ§€ν•˜μ§€ μ•ŠλŠ”λ‹€. λ©”λͺ¨λ¦¬λ₯Ό μ°¨μ§€ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 빅데이터λ₯Ό μ“Έ λ•ŒλŠ” Generatorκ°€ 훨씬 μš°μ„Έν•˜λ‹€κ³  ν•œλ‹€. 

tuple_g = (ord(s) for s in chars)  # 아직 λ©”λͺ¨λ¦¬λ₯Ό μƒμ„±ν•œ μƒνƒœκ°€ μ•„λ‹˜

 

이처럼 νŠœν”Œ μ•ˆμ— for문을 써주면 μ œλ„ˆλ ˆμ΄ν„° 객체가 μƒμ„±λœλ‹€. 아직 λ©”λͺ¨λ¦¬λ₯Ό μƒμ„±ν•œ μƒνƒœκ°€ μ•„λ‹ˆλΌλŠ” 것! 

 

(2) Array 

import array 
array_g = array.array('I', (ord(s) for s in chars))

 

arrayλ₯Ό importν•΄μ€€λ‹€. 처음 μ¨λ³΄μ•„μ„œ λ¬Έμ„œλ₯Ό μ°Ύμ•„μ„œ μ½μ–΄λ³΄μ•˜λ‹€. 

<array.array μ°Έκ³  λ¬Έμ„œ>

https://docs.python.org/3/library/array.html

 

array — Efficient arrays of numeric values — Python 3.9.6 documentation

array — Efficient arrays of numeric values This module defines an object type which can compactly represent an array of basic values: characters, integers, floating point numbers. Arrays are sequence types and behave very much like lists, except that the

docs.python.org

 

*** 좜λ ₯, μ‚¬μš©ν•΄λ³΄κΈ° 

print('EX2-1 - ', tuple_g)  
print('EX2-2 - ', next(tuple_g))
print('EX2-3 - ', next(tuple_g))
print('EX3-4 - ', array_g)
print('EX3-4 - ', array_g.tolist())

μ œλ„ˆλ ˆμ΄ν„°λŠ” next λ˜λŠ” for문을 μ΄μš©ν•˜μ—¬ 값을 κΊΌλ‚Ό 수 μžˆλ‹€. 

arrayλ₯Ό 리슀트둜 λ³€ν™˜ν•˜κ³  μ‹Άλ‹€λ©΄ tolist()λ₯Ό μ‚¬μš©ν•œλ‹€. 

 

 

*** μ œλ„ˆλ ˆμ΄ν„° for문으둜 μ‚¬μš©ν•˜κΈ° 

print('EX3-1 - ', ('%s' % c + str(n) for c in ['A', 'B', 'C', 'D'] for n in range(1, 11)))

for s in ('%s' % c + str(n) for c in ['A', 'B', 'C', 'D'] for n in range(1, 11)):
    print('EX3-2 - ', s)

for문으둜 μ œλ„ˆλ ˆμ΄ν„° κ°μ²΄μ—μ„œ 값듀을 ν•˜λ‚˜μ”© κΊΌλ‚΄μ£ΌλŠ” μ½”λ“œ  . 

 

 

 

- Tuple Advanced

*** packing & unpacking

print('EX5-1 - ', divmod(100, 9))
print('EX5-2 - ', divmod(*(100, 9)))
print('EX5-3 - ', *(divmod(100, 9)))

divmodλŠ” λͺ«κ³Ό λ‚˜λ¨Έμ§€λ₯Ό νŠœν”Œλ‘œ λ°˜ν™˜ν•΄μ£ΌλŠ” ν•¨μˆ˜μ΄λ‹€. νŠœν”Œ μ•žμ— *을 뢙이면 unpaking이 λœλ‹€λŠ” 것 !

 

x, y, *rest = range(10)
print('EX5-4 - ', x, y, rest)
x, y, *rest = range(2)
print('EX5-5 - ', x, y, rest)
x, y, *rest = 1, 2, 3, 4, 5
print('EX5-6 - ', x, y, rest)

 

μ°Έκ³ ) ** ---> dictionary λ₯Ό λ°›μŒ 

(ex) def test(*args, **args):

 

 

- Mutable (κ°€λ³€) vs Immutable (λΆˆλ³€) 

l = (10, 15, 20)
m = [10, 15, 20]

print('EX6-1 - ', l, m, id(l), id(m))

λ¦¬μŠ€νŠΈμ™€ νŠœν”Œ 객체λ₯Ό 각각 생성해쀀닀. 

# 객체λ₯Ό μƒˆλ‘œ 생성 ---> λ©”λͺ¨λ¦¬λ₯Ό 더 μž‘μ•„λ¨Ήμ„ μˆ˜λ„ μžˆλ‹€λŠ” 것 
l = l * 2
m = m * 2 

print('EX6-2 - ', l, m, id(l), id(m))

# μžμ²΄μ—μ„œ μ—°μ‚° 
l *= 2 
m *= 2

print('EX6-3 - ', l, m, id(l), id(m))

l = l*2 와 같은 μ½”λ“œλŠ” 객체λ₯Ό μƒˆλ‘œ μƒμ„±ν•œλ‹€λŠ” 것이닀. 좜λ ₯된 id값을 봐도 λ¦¬μŠ€νŠΈμ™€ νŠœν”Œ λͺ¨λ‘ μƒˆλ‘œμš΄ 객체가 μƒμ„±λœ 것을 μ•Œ 수 μžˆλ‹€. 

 

l *= 2 와 같이 μžμ²΄μ—μ„œ 연산을 ν•  λ•ŒλŠ” κ°€λ³€ν˜•μΈ λ¦¬μŠ€νŠΈλŠ” 객체λ₯Ό μƒˆλ‘œ λ§Œλ“€μ§€ μ•Šκ³ , λΆˆλ³€ν˜•μΈ νŠœν”Œμ€ 객체λ₯Ό μƒˆλ‘œ λ§Œλ“ λ‹€. 

 

 

-  sort vs sorted 

f_list = ['ornage', 'apple', 'mango', 'papaya', 'lemon', 'strawberry','coconut']

 

(1) sorted : μ •λ ¬ ν›„ μƒˆλ‘œμš΄ 객체 λ°˜ν™˜

print('EX7-1 - ', sorted(f_list))
print('EX7-2 - ', sorted(f_list, reverse=True)) # μ—­μˆœμœΌλ‘œ μ •λ ¬ 
print('EX7-3 - ', sorted(f_list, key=len)) # κΈΈμ΄μˆœμ„œ 
print('EX7-4 - ', sorted(f_list, key=lambda x: x[-1]))
print('EX7-5 - ', sorted(f_list, key=lambda x: x[-1], reverse=True))

print('EX7-6 - ', f_list)

sorted 의 μΈμžμ—λŠ” μ •λ ¬ν•  λ¦¬μŠ€νŠΈμ™€ μ •λ ¬ν•  쑰건을 λ„£μ–΄μ€€λ‹€. 

객체λ₯Ό μƒˆλ‘œ λ°˜ν™˜ν•˜κΈ° λ•Œλ¬Έμ—, 원본 λ¦¬μŠ€νŠΈμ—λŠ” λ³€ν™”κ°€ μ—†λ‹€. 

 

 

(2) sort : μ •λ ¬ ν›„ 객체 직접 λ³€κ²½ 

a = f_list.sort()

print('EX7-7 - ', f_list.sort(), f_list)
print('EX7-8 - ', f_list.sort(reverse=True), f_list)
print('EX7-9 - ', f_list.sort(key=len), f_list)
print('EX7-10 - ', f_list.sort(key=lambda x: x[-1]), f_list)
print('EX7-11 - ', f_list.sort(key=lambda x: x[-1], reverse=True), f_list)

sortλŠ” 객체λ₯Ό 직접 λ³€κ²½ν•˜κΈ° λ•Œλ¬Έμ—, f_list.sort() 자체λ₯Ό 좜λ ₯ν•˜λ©΄ None이 λ‚˜μ˜¨λ‹€. (None---> λ°˜ν™˜κ°’μ΄ μ—†λ‹€λŠ” 뜻) κ·Έλž˜μ„œ 원본인 f_listλ₯Ό 좜λ ₯ν•΄μ£Όμ–΄μ•Ό λ³€κ²½λœ 리슀트λ₯Ό λ³Ό 수 μžˆλ‹€. 

 

 

 

 

 

 

 

 

 

 

 

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리)

 

<이전 κΈ€>

https://silvercoding.tistory.com/21

 

[python 심화] 4. 데이터 λͺ¨λΈ(Data Model), Nametuple

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리) <이전 κΈ€> https://silvercoding.tistory.com/20 https://silvercoding.tistory.com/19 https://silvercoding.tistory.com/18 [python 심화] 1. 객체지ν–₯(OOP), 클..

silvercoding.tistory.com

 

 

<맀직 λ©”μ†Œλ“œ κ΄€λ ¨ λ¬Έμ„œ>

https://docs.python.org/3/reference/datamodel.html#special-method-names

 

3. Data model — Python 3.9.6 documentation

A class can implement certain operations that are invoked by special syntax (such as arithmetic operations or subscripting and slicing) by defining methods with special names. This is Python’s approach to operator overloading, allowing classes to define

docs.python.org

https://www.tutorialsteacher.com/python/magic-methods-in-python

 

Magic or Dunder Methods in Python

Python - Magic or Dunder Methods Magic methods in Python are the special methods that start and end with the double underscores. They are also called dunder methods. Magic methods are not meant to be invoked directly by you, but the invocation happens inte

www.tutorialsteacher.com

파이썬의 μ€‘μš”ν•œ 핡심 ν”„λ ˆμž„ μ›Œν¬ : μ‹œν€€μŠ€(Sequence), 반볡(Iterator), ν•¨μˆ˜(Functions), 클래슀(Class

 

 

 

- λ§€μ§λ©”μ†Œλ“œ 

n = 100 
print(dir(n)) # λͺ¨λ“  속성 및 λ©”μ†Œλ“œ 좜λ ₯ 

__xxx__ ----> 맀직 λ©”μ†Œλ“œ 

 

 

*** μ‚¬μš© 

print('EX1-1 - ', n + 200)
print('EX1-2 - ', n.__add__(200))
print('EX1-3 - ', n.__doc__)
print('EX1-4 - ', n.__bool__(), bool(n))
print('EX1-5 - ', n * 100, n.__mul__(100))

맀직 λ©”μ†Œλ“œλŠ” νŒŒμ΄μ¬μ—μ„œ 이미 μ •μ˜λœ λ©”μ„œλ“œλΌκ³  보면 λœλ‹€. 이보닀도 더 λ‹€μ–‘ν•œ 맀직 λ©”μ†Œλ“œλ“€μ΄ μžˆλ‹€. 

μ΄λŸ¬ν•œ μ •μˆ˜ν˜• νƒ€μž…μ˜ κ°μ²΄λŠ” κ·Έλƒ₯ + , * μ΄λŸ¬ν•œ κΈ°ν˜Έλ“€λ‘œ μ‚¬μš©ν•  수 μžˆκ² μ§€λ§Œ, 직접 클래슀λ₯Ό λ§Œλ“€μ–΄ μ‚¬μš©ν•  λ•ŒλŠ” 직접 μ •μ˜λ₯Ό ν•΄μ„œ μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€. 

 

 

 

 

- 클래슀 맀직 λ©”μ†Œλ“œ 예제 

(1) 클래슀 생성 

class Student:
    # 맀직 λ©”μ„œλ“œμž„. νŒŒμ΄μ¬μ—μ„œ 이미 μ •μ˜λœ λ©˜μ„œλ“œ 
    def __init__(self, name, height):
        self._name = name
        self._height = height

    def __str__(self):
        return 'Student Class Info : {}, {}'.format(self._name, self._height)

    def __ge__(self, x):
        print("Called >> __ge__ Method.")
        if self._height >= x._height:
            return True
        else:
            return False

    def __le__(self, x):
        print("Called >> __le__ Method")
        if self._height <= x._height:
            return True
        else:
            return False

    def __sub__(self, x):
        print('Called >> __sub__ Method.')
        return self._height - x._height

 

μœ„μ˜ λ¬Έμ„œμ—μ„œ κ°€μ Έμ˜¨ 맀직 λ©”μ„œλ“œ 의미 

__str__ ---> To get called by built-int str() method to return a string representation of a type.

__le__ ---> To get called on comparison using <= operator.

__ge__ ---> To get called on comparison using >= operator.

__sub__ ---> To get called on subtraction operation using - operator.

 

 

(2) μ‚¬μš© 

*** μΈμŠ€ν„΄μŠ€ 생성 

s1 = Student('James', 181)
s2 = Student('Mie', 165)

Student 클래슀의 μΈμŠ€ν„΄μŠ€ 생성!

 

*** 맀직 λ©”μ†Œλ“œ 좜λ ₯ 

print('EX2-1 - ', s1 >= s2)
print('EX2-2 - ', s1 <= s2)
print('EX2-3 - ', s1 - s2)
print('EX2-4 - ', s2 - s1)
print('EX2-5 - ', s1)
print('EX2-6 - ', s2)

ν΄λž˜μŠ€μ— λ§€μ§λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ 객체와 κ°μ²΄κ°„μ˜ λΉ„κ΅λ‘œ 받아듀이기 λ•Œλ¬Έμ— 였λ₯˜κ°€ λ‚œλ‹€. 

ν΄λž˜μŠ€μ—μ„œ 직접 μ •μ˜λ₯Ό ν•΄λ†¨μœΌλ―€λ‘œ 였λ₯˜κ°€ λ‚˜μ§€ μ•Šκ³  μ •μ˜ν•œ λŒ€λ‘œ λ‚˜μ˜¨λ‹€. 

이와같이 λ§€μ§λ©”μ†Œλ“œλ₯Ό 직접 μ •μ˜ν•˜μ—¬ μœ μš©ν•œ ν™œμš©μ΄ κ°€λŠ₯ν•˜λ‹€. 

 

 

 

- 클래슀 λ©”μ§λ©”μ†Œλ“œ μ‚¬μš© 예제 2

(1) 클래슀 생성 

class Vector(object):
    def __init__(self, *args):
        '''Create a vector, example : v = Vector(1, 2)'''
        if len(args) == 0:
            self._x, self._y = 0, 0
        else:
            self._x, self._y = args

    def __repr__(self):
        '''Returns the Vector information'''
        return 'Vector(%r, %r)' % (self._x, self._y)

    def __add__(self, other):
        '''Returns the vector addition of self and other'''
        return Vector(self._x + other._x, self._y + other._y)

    def __mul__(self, t):
        '''Returns the vector addition of self and other'''
        return Vector(self._x * t, self._y * t)

    def __bool__(self):
        return bool(max(self._x, self._y))

벑터λ₯Ό μƒμ„±ν•΄μ£ΌλŠ” ν΄λž˜μŠ€μ΄λ‹€. 

__add__λ©”μ†Œλ“œλŠ” 벑터끼리 각 μ’Œν‘œμ— λŒ€ν•œ λ§μ…ˆ, __mul__λ©”μ†Œλ“œλŠ” μ‹€μˆ˜λ₯Ό μΈμžμ— λ„£μ–΄μ£Όλ©΄ 각 μ’Œν‘œμ— κ³±ν•΄μ§€λŠ” 것을 κ΅¬ν˜„ν•œ 것이닀. __bool__λ©”μ†Œλ“œλŠ” x, y μ’Œν‘œ 쀑 큰 값이 0이 μ•„λ‹ˆλ©΄ Trueλ₯Ό λ°˜ν™˜ν•˜κ²Œ ν•΄μ€€λ‹€. (정말 κ΅¬ν˜„ν•˜κ³  싢은 λŒ€λ‘œ κ΅¬ν˜„ν•˜λ©΄ λœλ‹€!)

 

 

(2) μ‚¬μš© 

# Vector μΈμŠ€ν„΄μŠ€ 생성
v1 = Vector(3, 5)
v2 = Vector(15, 20)
v3 = Vector()

# 맀직 λ©”μ†Œλ“œ 좜λ ₯ 
print("EX3-1 - ", Vector.__init__.__doc__)
print("EX3-2 - ", Vector.__repr__.__doc__)
print("EX3-3 - ", Vector.__add__.__doc__)
print("EX3-4 - ", v1, v2, v3)
print("EX3-5 - ", v1 + v2)
print("EX3-6 - ", v1 * 4)
print("EX3-7 - ", v2 * 10)
print('EX3-8 - ', bool(v1), bool(v2))
print('EX3-9 - ', bool(v3))

__doc__ λ₯Ό μ‚¬μš©ν•˜λ©΄ μœ„μ—μ„œ μž‘μ„±ν–ˆλ˜ 주석 μ„€λͺ…이 좜λ ₯λœλ‹€. λ‚˜λ¨Έμ§€λ„ 잘 μ‹€ν–‰λ˜λ©΄ 성곡!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리)

 

<이전 κΈ€>

https://silvercoding.tistory.com/20

 

[python 심화] 3. 클래슀 λ©”μ†Œλ“œ, μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œ, μŠ€ν…Œμ΄ν‹± λ©”μ†Œλ“œ

μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ μ°Έκ³  (패캠 μˆ˜μ—… 정리) <이전 κΈ€> https://silvercoding.tistory.com/19 https://silvercoding.tistory.com/18 [python 심화] 1. 객체지ν–₯(OOP), 클래슀 기초 μ‚¬μš© μ½”λ“œ - 패캠 μˆ˜μ—… μ½”λ“œ..

silvercoding.tistory.com

 

 

<데이터 λͺ¨λΈ μ°Έκ³  λ¬Έμ„œ> 

https://docs.python.org/3/reference/datamodel.html

 

3. Data model — Python 3.9.6 documentation

A class can implement certain operations that are invoked by special syntax (such as arithmetic operations or subscripting and slicing) by defining methods with special names. This is Python’s approach to operator overloading, allowing classes to define

docs.python.org

 

[ 객체 (Objects)λŠ” 파이썬이 데이터(data)λ₯Ό μΆ”μƒν™”ν•œ 것(abstraction)μž…λ‹ˆλ‹€. 파이썬 ν”„λ‘œκ·Έλž¨μ˜ λͺ¨λ“  λ°μ΄ν„°λŠ” κ°μ²΄λ‚˜ 객체 κ°„μ˜ κ΄€κ³„λ‘œ ν‘œν˜„λ©λ‹ˆλ‹€.

 

λͺ¨λ“  κ°μ²΄λŠ” 아이덴티티(identity), ν˜•(type), κ°’(value)을 κ°–μŠ΅λ‹ˆλ‹€. 객체의 μ•„이덴티티 λŠ” ν•œ 번 λ§Œλ“€μ–΄μ§„ ν›„μ—λŠ” λ³€κ²½λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ©”λͺ¨λ¦¬μƒμ—μ„œμ˜ 객체의 μ£Όμ†Œλ‘œ 생각해도 μ’‹μŠ΅λ‹ˆλ‹€. γ€ˆis〉 μ—°μ‚°μžλŠ” 두 객체의 아이덴티티λ₯Ό λΉ„κ΅ν•©λ‹ˆλ‹€. id() ν•¨μˆ˜λŠ” 아이덴티티λ₯Ό μ •μˆ˜λ‘œ ν‘œν˜„ν•œ 값을 λŒλ €μ€λ‹ˆλ‹€. ]

 

 

μœ„μ˜ λ¬Έμ„œμ—μ„œ λ‚˜μ™€μžˆλŠ” 객체의 μ„€λͺ…이닀. λͺ¨λ“  κ°μ²΄λŠ” id, type, valueλ₯Ό κ°–λŠ”λ‹€. 예λ₯Ό λ“€μ–΄ 

a = 7 
print(id(a), type(a), dir(a))

μ΄λŸ¬ν•œ aλΌλŠ” λ³€μˆ˜λ„ κ°μ²΄λΌλŠ” 것이닀. λ”°λΌμ„œ id, type, valueλ₯Ό λͺ¨λ‘ κ°–κ³  μžˆλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€. 

 

 

 

- λ„€μž„νŠΈ νŠœν”Œ 

<두 점 μ‚¬μ΄μ˜ 거리λ₯Ό κ΅¬ν•˜λŠ” 예제>

(1) 일반적인 νŠœν”Œ μ‚¬μš©

pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)
from math import sqrt
from typing import ClassVar
line_leng1 = sqrt((pt2[0] - pt1[0]) ** 2 + (pt2[1] - pt1[1]) ** 2)
print('EX1-1 : ', line_leng1)

μ΄λ ‡κ²Œ 인덱슀λ₯Ό μ΄μš―ν•˜μ—¬ κ΅¬ν•˜κ²Œ λœλ‹€. μ΄λ ‡κ²Œ κ°„λ‹¨ν•œ μ˜ˆμ œμ—μ„œλŠ” 상관이 μ—†κΈ΄ ν•˜μ§€λ§Œ 가독성이 λ–¨μ–΄μ§€λŠ” 것 κ°™κΈ΄ ν•˜λ‹€. 쑰금 더 λ³΅μž‘ν•œ μˆ˜μ‹μ΄λΌλ©΄ μ‹€μˆ˜ν•˜κΈ° λ”±μ’‹λ‹€! xκ°’ 끼리 λΉΌμ£Όκ³  , yκ°’ 끼리 λΉΌμ£ΌλŠ” 것을 더 λͺ…μ‹œμ μœΌλ‘œ 적어쀄 수 μžˆλŠ” named tuple을 μ‚¬μš©ν•΄ 보자! 

 

 

(2) λ„€μž„λ“œ νŠœν”Œ μ‚¬μš© 

*** named tuple 선언법 

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) # Defalult=False

# 좜λ ₯ 
print('EX2-1 - ', Point1, Point2, Point3, Point4)

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

# 객체 생성 
print()
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('EX2-2 - ', p1, p2, p3, p4, p5)

collections의 namedtuple을 importν•΄μ€€λ‹€. λ„€μž„λ“œ νŠœν”Œμ€ 클래슀둜 ν•˜κΈ°μ—” λ„ˆλ¬΄ ν—€λΉ„ν•˜κ³ , νŠœν”Œμ— 이름을 μ£Όκ³  싢을 λ•Œ μ‚¬μš©ν•œλ‹€. 

 

point4μ—μ„œλŠ” xκ°€ μ€‘λ³΅μœΌλ‘œ λ“€μ–΄ κ°€ 있고, class도 λ³€μˆ˜λͺ…μœΌλ‘œ μ‚¬μš©ν•  수 μ—†μœΌλ―€λ‘œ rename=Trueλ₯Ό μ„€μ •ν•΄ 놓지 μ•ŠλŠ”λ‹€λ©΄ 였λ₯˜κ°€ λ‚  것이닀. 

rename=Trueλ₯Ό μ„€μ •ν•΄ λ†“μœΌλ©΄ μœ„μ™€κ°™μ΄ μ•Œμ•„μ„œ λ³€μˆ˜λͺ…이 λ°”λ€Œκ²Œ λœλ‹€. 

 

 

*** μ‚¬μš©

print('EX3-1 - ', p1[0] + p2[1])  # Index Error 주의 
print('EX3-2 - ', p1.x + p2.y) # 클래슀 λ³€μˆ˜ μ ‘κ·Ό 방식

# Unpacking 
x, y = p3

print('EX3-3 - ', x + y)

κΈ°μ‘΄ tupleκ³Ό 같이 Unpacking도 κ°€λŠ₯ν•˜λ‹€. 

 

 

*** λ„€μž„λ“œνŠœν”Œμ˜ λ©”μ†Œλ“œ 

  • _make() : μƒˆλ‘œμš΄ 객체λ₯Ό 생성 (리슀트 ---> λ„€μž„λ“œνŠœν”Œ) 
p4 = Point1._make(temp)
print('EX4-1 - ', p4)
  • _field : ν•„λ“œ  λ„€μž„ 확인 
print('EX4-2 - ', p1._fields, p2._fields, p3._fields)
  • _asdict() : OrderDict λ°˜ν™˜ 
# _asdict() : OrderDict λ°˜ν™˜ 
print('EX4-3 - ', p1._asdict(), p1._asdict(), p3._asdict(), p4._asdict())
  • _replace() : μˆ˜μ •λœ 'μƒˆλ‘œμš΄' 객체 λ°˜ν™˜ 
print('EX4-4 - ', p2._replace(y=100)) 

μ΄λ ‡κ²Œ ν•„λ“œμ— λŒ€ν•œ 값을 변경해쀄 수 μžˆλŠ”λ°, μ΄λŠ” 리슀트 처럼 값이 λ³€κ²½λ˜λŠ” 것이 μ•„λ‹ˆλΌ , μ•„μ˜ˆ μƒˆλ‘œμš΄ 객체λ₯Ό λ°˜ν™˜ν•΄ μ£ΌλŠ” 것이닀. 

 

 

 

 

*** 예제

# λ„€μž„λ“œ νŠœν”Œ μ„ μ–Έ 
Point = namedtuple('Point', 'x y')

# 두 점 μ„ μ–Έ 
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

# 두 점 μ‚¬μ΄μ˜ 거리 계산
line_leng2 = sqrt((pt2.x - pt1.x) ** 2 + (pt2.y - pt1.y) ** 2)

# 좜λ ₯
print("EX1-2 - ", line_leng2)
print("EX1-3 - ", line_leng1 == line_leng2)

 

κ·Έλž˜μ„œ μ›λž˜ ν•˜λ €ν–ˆλ˜ 예제λ₯Ό λ„€μž„λ“œ νŠœν”Œμ„ μ‚¬μš©ν•˜λ©΄ μœ„μ™€ κ°™λ‹€. λ„€μž„λ“œνŠœν”Œμ„ μ‚¬μš©ν•˜λ©΄ μœ„μ™€κ°™μ΄ 더 λͺ…μ‹œμ μœΌλ‘œ μˆ˜μ‹μ„ μž‘μ„±ν•΄μ€„ 수 μžˆλ‹€. 

 

 

 

- λ„€μž„λ“œ νŠœν”Œ μ‹€μŠ΅ 

학생 그룹을 μƒμ„±ν•˜λŠ” 예제, 4개의 반(A, B, C, D) μ—μ„œ 각각 20λͺ…μ˜ 학생이 쑴재

 

(1) λ„€μž„λ“œ νŠœν”Œ μ„ μ–Έ 

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

 

 

(2) κ·Έλ£Ή 리슀트 μ„ μ–Έ (List Comprehension μ‚¬μš©)

# List Comprehension
numbers = [str(n) for n in range(1, 21)]
ranks = 'A B C D'.split()
print(ranks, numbers)

print()

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

print('EX5-1 - ', len(students))
print('EX5-2 - ', students[4].rank)

numberλŠ” 1~20의 문자λ₯Ό λ‹΄κ³ μžˆλŠ” 리슀트, ranksλŠ” A~B의 문자λ₯Ό λ‹΄κ³  μžˆλŠ” λ¦¬μŠ€νŠΈμ΄λ‹€. 

이제 λ„€μž„λ“œ νŠœν”Œμ˜ 객체듀을 list comprehension을 μ‚¬μš©ν•˜μ—¬ 생성해 μ€€λ‹€. 총 20 * 4 = 80 개의 객체가 리슀트 μ•ˆμ— 생성될 것이닀. 

 

 

*** 가독성이 λ–¨μ–΄μ§€μ§€λ§Œ ν•œλ²ˆμ— 그룹리슀트λ₯Ό λ§Œλ“œλŠ”λ²• 

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

print('EX6-1 - ', len(students2))
print('EX6-1 - ', students2)

λ¦¬μŠ€νŠΈμ— ν•œλ²ˆμ— λ•Œλ €λ°•μ•„ μ£ΌλŠ” 법이닀. 뭐든지 κ³Όν•˜λ©΄ 독이 λ˜λŠ” 것 κ°™λ‹€. 가독성이 λ–¨μ–΄μ§€μ§€λ§Œ 이런 방법도 μžˆλ‹€λŠ” 것을 μ•Œμ•„λ‘κΈ°. 

 

 

+ Recent posts