일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Class
- Convert Sorted List to Binary Search Tree
- Generator
- data science
- concurrency
- 715. Range Module
- kaggle
- 컴퓨터의 구조
- Substring with Concatenation of All Words
- 30. Substring with Concatenation of All Words
- 43. Multiply Strings
- t1
- Python Implementation
- 109. Convert Sorted List to Binary Search Tree
- attribute
- Python
- iterator
- 밴픽
- Regular Expression
- LeetCode
- Python Code
- 운영체제
- DWG
- 315. Count of Smaller Numbers After Self
- 프로그래머스
- Decorator
- 파이썬
- 시바견
- Protocol
- shiba
- Today
- Total
Scribbling
Python: Object References 본문
ID operator returns the object's memory address. We use it to compare objects' identities.
morgan = {'name': 'hoesu', 'age':29}
hoesu = morgan
print(hoesu is morgan)
print(id(hoesu), id(morgan))
"==" operator calls __eq__() method in dict class and checks whether the objects have the same value or not.
morgan = {'name': 'hoesu', 'age':29}
anonymous = {'name': 'hoesu', 'age':29}
print(morgan == anonymous)
print(morgan is anonymous)
What is very important here is that 'Equality' does not necessarily mean 'Identity'.
Using mutable types as parameter defaults is a bad idea. Let's look at the below example.
class HauntedBus:
def __init__(self, passengers=[]):
self.passengers = passengers
def pick(self, name):
self.passengers.append(name)
def drop(self, name):
self.passengers.remove(name)
bus1 = HauntedBus()
bus1.pick('morgan')
print(bus1.passengers)
bus2 = HauntedBus()
print(bus2.passengers)
There's a guest in bus2 even though it never picked up anyone. What's wrong?
- self.passengers is aliasing of a default parameter.
- default parameter is function's property when it is defined (during import time).
- If HauntedBus is initiated without parameters, the same default parameter is used.
Defensive programming with mutable parameters
class TwilightBus:
def __init__(self, passengers=None):
if passengers is None:
self.passengers = []
else:
self.passengers = passengers
def pick(self, name):
self.passengers.append(name)
def drop(self, name):
self.passengers.remove(name)
people = ['morgan', 'JY', 'hoesu', 'HS']
bus1 = TwilightBus(people)
bus1.drop('morgan')
bus1.drop('HS')
print(bus1.passengers)
print(people)
We only dropped people from bus, but they are removed from the list at the same time. We have to be extra cautious when dealing with mutable parameters.
import copy
class TwilightBus:
def __init__(self, passengers=None):
if passengers is None:
self.passengers = []
else:
# self.passengers = list(passengers)
self.passengers = copy.deepcopy(passengers)
Now, about "del". "del" is to get rid of the name, not the object itself. In CPython, garbage collection is based on 'reference count'.
import weakref
s1 = {1, 2, 3}
s2 = s1
def bye():
print('Garbage collected object')
e = weakref.finalize(s1, bye)
print(e.alive)
del s1
print(e.alive)
s2 = 'spam'
print(e.alive)
Above example clearly shows that an object is collected not by del, but when it is not reachable.
We used weakref in the above example. 'Weak Reference' means it references an object without increasing 'reference count'. As a result, it does not interfere with garbage collection.
WeakKeyDictionary, WeakValueDictionary, WeakSet are recommeded when creating weak references.
import weakref
class iamclass:
instances = weakref.WeakSet()
@classmethod
def register(cls, instance):
cls.instances.add(instance)
def __init__(self):
self.register(self)
@classmethod
def showAll(cls):
print(cls.instances)
a = iamclass()
b = iamclass()
c = iamclass()
iamclass.showAll()
'Computer Science > Python' 카테고리의 다른 글
Python: Sequence Protocol (0) | 2022.04.06 |
---|---|
Python: Pythonic Object (0) | 2022.04.05 |
Python: Decorator & Closure (0) | 2022.03.29 |
Python: Design Patterns (0) | 2022.03.25 |
Python: Memoryview function (0) | 2022.03.23 |