-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmagic_methods.py
228 lines (167 loc) · 6.8 KB
/
magic_methods.py
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
'''Special (Magic) Methods'''
# Names of these methods begin and end with __. An example is __init__ which
# initializes a newly created object from its class and any arguments that were
# passed in. Many basic tasks in python can be done with non-object-oriented
# looking syntax (a + b, for example). What's really happening here is a
# kind of "syntactic sugar" that maps to an object-oriented pattern underneath.
# For example, the __add__ method allows us to use the '+' operator, the
# __contains__ method allows us to use the 'in' keyword (see polymorphism.py),
# and so on.
# Example: override the __add__ method will in turn affect the '+' operator.
class TestInt(int):
def __add__(self, num):
return 100
a = TestInt(5)
b = TestInt(3)
print(a + b) # 100
# Example: create a method that compares two words but is case insensitive.
class Word(str):
def __eq__(self, word):
return self.lower() == word.lower()
a = Word('haha')
b = Word('HAHA')
print(a == b) # True
# In those two examples we inherited from int and str, but we don't have to:
class Word():
def __init__(self, text):
self.text = text
def __eq__(self, word):
return self.text.lower() == word.text.lower()
a = Word('ha')
b = Word('HA')
print(a == b) # True
# Magic Methods for comparison
# -----------------------------------------------------------------------------
def __eq__(self, other): # self == other
pass
def __ne__(self, other): # self != other
pass
def __lt__(self, other): # self < other
pass
def __gt__(self, other): # self > other
pass
def __le__(self, other): # self <= other
pass
def __ge__(self, other): # self >= other
pass
# Magic Methods for math
# -----------------------------------------------------------------------------
def __add__(self, other): # self + other
pass
def __sub__(self, other): # self - other
pass
def __mul__(self, other): # self * other
pass
def __floordiv__(self, other): # self // other
pass
def __truediv__(self, other): # self / other
pass
def __mod__(self, other): # self % other
pass
def __pow__(self, other): # self ** other
pass
# Others...
# -----------------------------------------------------------------------------
# x.__init__() # initialize an instance
# x.__repr__() # the official representation as a string
# x.__str__() # the informal value as a string
# x.__bytes__() # the informal value as a byte array
# x.__format__() # the value as a formatted string
# seq.__iter__() # iterate through a sequence
# seq.__next__() # get the next value from an iterator
# seq.__reversed__() # create an iterator in reverse order
# x.__len__() # number of items
# x.__copy__() # create a custom object copy
# The list goes on: http://www.diveintopython3.net/special-method-names.html
# You can list all the magic methods related to classes by using dir():
print(dir(list))
# ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
# '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
# '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__',
# '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__',
# '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
# '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__',
# '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend',
# 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
# You can list all the magic methods related to functions by using dir():
def my_function():
'''Test function that does nothing'''
pass
print(dir(my_function))
# ['__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__']
# __str__ and __repr__
# -----------------------------------------------------------------------------
print(a) # <__main__.Word object at 0x101ca8828>
print(repr(a)) # <__main__.Word object at 0x101ca8828>
class Word():
def __init__(self, text):
self.text = text
def __str__(self):
return self.text
def __repr__(self):
return 'Word("' + self.text + '")'
a = Word('Ha')
print(a) # Ha
print(repr(a)) # Word("Ha")
# Another __str__ example
# -----------------------------------------------------------------------------
class Player():
def __init__(self, name):
self.name = name
self.lives = 3
self.level = 1
self.score = 0
def __str__(self):
return ('Name: {0.name}, Lives: {0.lives}, Level: {0.level}, '
'Score: {0.score}'.format(self))
player1 = Player('Morty')
print(player1) # Name: Morty, Lives: 3, Level: 1, Score: 0
# __dict__
# -----------------------------------------------------------------------------
# Another magic method is __dict__. It's used to return the dictionary used to
# store an object’s attributes.
print(player1.__dict__)
# {'name': 'Morty', 'lives': 3, 'level': 1, 'score': 0}
# __file__
# -----------------------------------------------------------------------------
# This magic method is available to modules loaded in. If you want to take a
# look at the actual file to read the comments and docstring there, you can
# use the __file__ method to show you the path to where this module lives:
import os
import flask
print(os.__file__)
# /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/os.py
print(flask.__file__)
# /usr/local/lib/python3.7/site-packages/flask/__init__.py
# __doc__
# -----------------------------------------------------------------------------
# prints the docstring of a module, function or class:
import random
print(random.__doc__)
print(random.choice.__doc__)
# tl:dr
# __len__, __reversed__, __class__, __name__
# -----------------------------------------------------------------------------
normal_sequence = [1, 2, 3, 4, 5]
class CustomSequence():
def __len__(self):
return 5
def __getitem__(self, index):
return 'x{}'.format(index)
class CustomReversed():
def __reversed__(self):
return 'Reversed!'
for item in normal_sequence, CustomSequence(), CustomReversed():
print('\n{}: '.format(item.__class__.__name__), end='')
for i in reversed(item):
print(i, end=", ")
print('')
# list: 5, 4, 3, 2, 1,
# CustomSequence: x4, x3, x2, x1, x0,
# CustomReversed: R, e, v, e, r, s, e, d, !,