μ½λ - ν¨μΊ μμ μ½λ μ°Έκ³ (ν¨μΊ μμ μ 리)
<μ΄μ κΈ>
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λ©μλλ μμν΄λμ€μμ ꡬνν΄μ£Όμ§ μμλ λΆλͺ¨μ ν΄λμ€μ λ©μλκ° μ€νλλ€.
'νλ‘κ·Έλλ° μΈμ΄ > Python' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[python μ¬ν] 13. μ½λ£¨ν΄ (coroutine) , yield from (0) | 2021.07.19 |
---|---|
[python μ¬ν] 12. λ΄λΆ iter ν¨μ, μ λλ μ΄ν°(Generator) (0) | 2021.07.17 |
[python μ¬ν] 10. copy & deep copy (0) | 2021.07.10 |
[python μ¬ν] 9. λ³μ λ²μ, Closure, Decorator (0) | 2021.07.09 |
[python μ¬ν] 8. μΌκΈ ν¨μ, μ΅λͺ ν¨μ, callable, 맀κ°λ³μ, signature, partial (0) | 2021.07.09 |