Skip to content

Commit fa2a99a

Browse files
committed
More explanation for metaclass methods with examples
1 parent 95beaf9 commit fa2a99a

File tree

4 files changed

+347
-53
lines changed

4 files changed

+347
-53
lines changed

kochi-python-oct-2018/Design Patterns - Creational Patterns.ipynb

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"name": "stdout",
5151
"output_type": "stream",
5252
"text": [
53-
"<__main__.A object at 0x7f7cf97e5be0> <__main__.A object at 0x7f7cf97e5be0>\n"
53+
"<__main__.A object at 0x7fd2083e9c18> <__main__.A object at 0x7fd2083e9c18>\n"
5454
]
5555
},
5656
{
@@ -89,17 +89,17 @@
8989
" \n",
9090
" @classmethod\n",
9191
" def single_new(mcs,cls,bases=(),dct={}):\n",
92-
" print('__new__:',mcs,cls)\n",
92+
" print('__new__:',mcs,cls, type(cls))\n",
9393
" if not cls.instance:\n",
9494
" cls.instance = object.__new__(cls)\n",
9595
" \n",
9696
" return cls.instance\n",
9797
"\n",
9898
" @classmethod\n",
99-
" def __prepare__(cls, name, bases, **kwargs):\n",
100-
" print('__prepare__:',cls)\n",
101-
" cls.instance = None\n",
102-
" return {'__new__': cls.single_new}"
99+
" def __prepare__(mcs, cls, bases, **kwargs):\n",
100+
" print('__prepare__:',mcs,cls)\n",
101+
" mcs.instance = None\n",
102+
" return {'__new__': mcs.single_new}"
103103
]
104104
},
105105
{
@@ -111,7 +111,7 @@
111111
"name": "stdout",
112112
"output_type": "stream",
113113
"text": [
114-
"__prepare__: <class '__main__.SingletonType'>\n"
114+
"__prepare__: <class '__main__.SingletonType'> Singular\n"
115115
]
116116
}
117117
],
@@ -130,9 +130,9 @@
130130
"name": "stdout",
131131
"output_type": "stream",
132132
"text": [
133-
"__new__: <class '__main__.SingletonType'> <class '__main__.Singular'>\n",
134-
"__new__: <class '__main__.SingletonType'> <class '__main__.Singular'>\n",
135-
"<__main__.Singular object at 0x7f7cf8f84358> <__main__.Singular object at 0x7f7cf8f84358>\n"
133+
"__new__: <class '__main__.SingletonType'> <class '__main__.Singular'> <class '__main__.SingletonType'>\n",
134+
"__new__: <class '__main__.SingletonType'> <class '__main__.Singular'> <class '__main__.SingletonType'>\n",
135+
"<__main__.Singular object at 0x7fd2083863c8> <__main__.Singular object at 0x7fd2083863c8>\n"
136136
]
137137
},
138138
{
@@ -170,9 +170,9 @@
170170
" \"\"\" A type for Singleton classes (overrides __call__) \"\"\" \n",
171171
" \n",
172172
" @classmethod\n",
173-
" def __prepare__(cls, name, bases, **kwargs):\n",
174-
" print('__prepare__:',cls)\n",
175-
" cls.instance = None\n",
173+
" def __prepare__(mcs, cls, bases, **kwargs):\n",
174+
" print('__prepare__:',mcs)\n",
175+
" mcs.instance = None\n",
176176
" return {}\n",
177177
"\n",
178178
" def __call__(cls, *args, **kwargs):\n",
@@ -213,7 +213,7 @@
213213
"__call__: <class '__main__.Alone'>\n",
214214
"<class '__main__.Alone'> creating instance () {}\n",
215215
"__call__: <class '__main__.Alone'>\n",
216-
"<__main__.Alone object at 0x7f7cf8f84ef0> <__main__.Alone object at 0x7f7cf8f84ef0>\n"
216+
"<__main__.Alone object at 0x7fd208386ef0> <__main__.Alone object at 0x7fd208386ef0>\n"
217217
]
218218
},
219219
{
@@ -290,7 +290,7 @@
290290
"name": "stdout",
291291
"output_type": "stream",
292292
"text": [
293-
"Mechanical Part id: 0x7f7cf8f91748 => suspension, frame, leaf spring\n"
293+
"Mechanical Part id: 0x7fd20838f828 => suspension, frame, leaf spring\n"
294294
]
295295
}
296296
],
@@ -308,8 +308,8 @@
308308
"name": "stdout",
309309
"output_type": "stream",
310310
"text": [
311-
"Mechanical Part id: 0x7f7cf8f919e8 => suspension, frame, leaf spring\n",
312-
"Mechanical Part id: 0x7f7cf8f91a58 => suspension, frame, leaf spring\n"
311+
"Mechanical Part id: 0x7fd20838fa20 => suspension, frame, leaf spring\n",
312+
"Mechanical Part id: 0x7fd20838f8d0 => suspension, frame, leaf spring\n"
313313
]
314314
}
315315
],
@@ -330,7 +330,7 @@
330330
" \"\"\" A metaclass for Prototypes \"\"\"\n",
331331
"\n",
332332
" @classmethod\n",
333-
" def __prepare__(cls, name, bases, **kwargs):\n",
333+
" def __prepare__(mcs, cls, bases, **kwargs):\n",
334334
" return {'clone': lambda x: copy.deepcopy(x)}\n"
335335
]
336336
},
@@ -371,8 +371,8 @@
371371
"name": "stdout",
372372
"output_type": "stream",
373373
"text": [
374-
"Bone id: 0x7f7cf8f91e48 => thigh bone, thigh, hip joint\n",
375-
"Bone id: 0x7f7cf8f91fd0 => collar bone, shoulder bone, shoulder joint\n"
374+
"Bone id: 0x7fd20838ff28 => thigh bone, thigh, hip joint\n",
375+
"Bone id: 0x7fd20838ff60 => collar bone, shoulder bone, shoulder joint\n"
376376
]
377377
}
378378
],
@@ -505,6 +505,13 @@
505505
"print(\"Joel's Role=>\",joel.get_role())"
506506
]
507507
},
508+
{
509+
"cell_type": "markdown",
510+
"metadata": {},
511+
"source": [
512+
"### Metaclass solution for Factory"
513+
]
514+
},
508515
{
509516
"cell_type": "code",
510517
"execution_count": 22,
@@ -671,9 +678,16 @@
671678
"Employee2.test()"
672679
]
673680
},
681+
{
682+
"cell_type": "markdown",
683+
"metadata": {},
684+
"source": [
685+
"## Question Time"
686+
]
687+
},
674688
{
675689
"cell_type": "code",
676-
"execution_count": 28,
690+
"execution_count": 27,
677691
"metadata": {},
678692
"outputs": [],
679693
"source": [
@@ -688,7 +702,7 @@
688702
},
689703
{
690704
"cell_type": "code",
691-
"execution_count": 31,
705+
"execution_count": 28,
692706
"metadata": {},
693707
"outputs": [
694708
{
@@ -705,7 +719,7 @@
705719
"traceback": [
706720
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
707721
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
708-
"\u001b[0;32m<ipython-input-31-21f8882911b5>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;31m# Why this fails ??\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
722+
"\u001b[0;32m<ipython-input-28-7bcbd794dda3>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;31m# Why this fails ?? How to fix it ?\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
709723
"\u001b[0;31mAttributeError\u001b[0m: 'C' object has no attribute 'func'"
710724
]
711725
}

kochi-python-oct-2018/Design Patterns - Structural.ipynb

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
" # A proxy almost always wraps up the object it proxies to\n",
3131
" def __init__(self, part):\n",
3232
" self.part = part\n",
33+
" # Question - Why the self.__class__ ?\n",
3334
" self.__class__.parts_count += 1\n",
3435
" count = self.__class__.parts_count\n",
3536
" # Register the part!\n",
@@ -73,6 +74,7 @@
7374
"name": "stdout",
7475
"output_type": "stream",
7576
"text": [
77+
"__prepare__: <class '__main__.PartsTypeProxyFactory'> Part\n",
7678
"__init__: <class '__main__.Part'>\n"
7779
]
7880
}
@@ -86,20 +88,22 @@
8688
" print('__init__:',cls)\n",
8789
" type.__init__(cls, *args)\n",
8890
" \n",
89-
" def my_new(cls,name,bases=(),dct={}):\n",
90-
" print(cls,name)\n",
91+
" @classmethod\n",
92+
" def my_new(mcs,cls,bases=(),dct={}):\n",
93+
" print('__new__:',mcs,cls)\n",
9194
" instance = object.__new__(cls)\n",
92-
" # instance = object.__new__(cls)\n",
95+
"\n",
9396
" return instance\n",
9497
" \n",
9598
" @classmethod\n",
9699
" def create(cls, *args, **kwargs):\n",
97-
" print('create:',args)\n",
100+
" print('create:',cls,args)\n",
98101
" return PartProxy(Part(*args, **kwargs))\n",
99102
" \n",
100103
" @classmethod\n",
101-
" def __prepare__(cls, name, bases, **kwargs):\n",
102-
" return {'__new__': cls.my_new}\n",
104+
" def __prepare__(mcs, cls, bases, **kwargs):\n",
105+
" print('__prepare__:',mcs,cls)\n",
106+
" return {'__new__': mcs.my_new}\n",
103107
"\n",
104108
"\n",
105109
"class Part(metaclass=PartsTypeProxyFactory):\n",
@@ -126,18 +130,18 @@
126130
"name": "stdout",
127131
"output_type": "stream",
128132
"text": [
129-
"create: ('Nut',)\n",
130-
"<class '__main__.Part'> Nut\n",
133+
"create: <class '__main__.PartsTypeProxyFactory'> ('Nut',)\n",
134+
"__new__: <class '__main__.PartsTypeProxyFactory'> <class '__main__.Part'>\n",
131135
"__init__: Nut None\n",
132-
"{1: <__main__.Part object at 0x7fb5744a3f28>}\n",
133-
"create: ('Bolt', <__main__.PartProxy object at 0x7fb5744a3fd0>)\n",
134-
"<class '__main__.Part'> Bolt\n",
136+
"{1: <__main__.Part object at 0x7f9478a3cf60>}\n",
137+
"create: <class '__main__.PartsTypeProxyFactory'> ('Bolt', <__main__.PartProxy object at 0x7f9478a3cf28>)\n",
138+
"__new__: <class '__main__.PartsTypeProxyFactory'> <class '__main__.Part'>\n",
135139
"__init__: Bolt Nut, parent: None \n",
136-
"{1: <__main__.Part object at 0x7fb5744a3f28>, 2: <__main__.Part object at 0x7fb5744a3a58>}\n",
137-
"create: ('Screw', <__main__.PartProxy object at 0x7fb5744a3978>)\n",
138-
"<class '__main__.Part'> Screw\n",
140+
"{1: <__main__.Part object at 0x7f9478a3cf60>, 2: <__main__.Part object at 0x7f9478a3c9e8>}\n",
141+
"create: <class '__main__.PartsTypeProxyFactory'> ('Screw', <__main__.PartProxy object at 0x7f9478a3ceb8>)\n",
142+
"__new__: <class '__main__.PartsTypeProxyFactory'> <class '__main__.Part'>\n",
139143
"__init__: Screw Bolt, parent: Nut, parent: None \n",
140-
"{1: <__main__.Part object at 0x7fb5744a3f28>, 2: <__main__.Part object at 0x7fb5744a3a58>, 3: <__main__.Part object at 0x7fb5744a3dd8>}\n"
144+
"{1: <__main__.Part object at 0x7f9478a3cf60>, 2: <__main__.Part object at 0x7f9478a3c9e8>, 3: <__main__.Part object at 0x7f9478a3c9b0>}\n"
141145
]
142146
}
143147
],
@@ -176,9 +180,9 @@
176180
{
177181
"data": {
178182
"text/plain": [
179-
"{1: <__main__.Part at 0x7fb5744a3f28>,\n",
180-
" 2: <__main__.Part at 0x7fb5744a3a58>,\n",
181-
" 3: <__main__.Part at 0x7fb5744a3dd8>}"
183+
"{1: <__main__.Part at 0x7f9478a3cf60>,\n",
184+
" 2: <__main__.Part at 0x7f9478a3c9e8>,\n",
185+
" 3: <__main__.Part at 0x7f9478a3c9b0>}"
182186
]
183187
},
184188
"execution_count": 5,
@@ -220,10 +224,10 @@
220224
"name": "stdout",
221225
"output_type": "stream",
222226
"text": [
223-
"create: ('Frame',)\n",
224-
"<class '__main__.Part'> Frame\n",
227+
"create: <class '__main__.PartsTypeProxyFactory'> ('Frame',)\n",
228+
"__new__: <class '__main__.PartsTypeProxyFactory'> <class '__main__.Part'>\n",
225229
"__init__: Frame None\n",
226-
"{1: <__main__.Part object at 0x7fb5744a3f28>, 2: <__main__.Part object at 0x7fb5744a3a58>, 3: <__main__.Part object at 0x7fb5744a3dd8>, 4: <__main__.Part object at 0x7fb574490e48>}\n",
230+
"{1: <__main__.Part object at 0x7f9478a3cf60>, 2: <__main__.Part object at 0x7f9478a3c9e8>, 3: <__main__.Part object at 0x7f9478a3c9b0>, 4: <__main__.Part object at 0x7f9478a2af98>}\n",
227231
"Joining with part Frame, parent: None \n"
228232
]
229233
}
@@ -299,7 +303,7 @@
299303
{
300304
"data": {
301305
"text/plain": [
302-
"{3: <__main__.Part at 0x7fb5744a3dd8>, 4: <__main__.Part at 0x7fb574490e48>}"
306+
"{3: <__main__.Part at 0x7f9478a3c9b0>, 4: <__main__.Part at 0x7f9478a2af98>}"
303307
]
304308
},
305309
"execution_count": 12,
@@ -349,7 +353,7 @@
349353
{
350354
"data": {
351355
"text/plain": [
352-
"{4: <__main__.Part at 0x7fb574490e48>}"
356+
"{4: <__main__.Part at 0x7f9478a2af98>}"
353357
]
354358
},
355359
"execution_count": 15,
@@ -529,6 +533,13 @@
529533
"print(rect.area())"
530534
]
531535
},
536+
{
537+
"cell_type": "markdown",
538+
"metadata": {},
539+
"source": [
540+
"### Metaclass Solution"
541+
]
542+
},
532543
{
533544
"cell_type": "code",
534545
"execution_count": 22,
@@ -603,9 +614,9 @@
603614
"output_type": "stream",
604615
"text": [
605616
"Metaclass=> <class '__main__.PolygonType'> Rectangle\n",
606-
"Attaching function <function rectangle_valid at 0x7fb57443e1e0> as is_valid method\n",
617+
"Attaching function <function rectangle_valid at 0x7f94781d3510> as is_valid method\n",
607618
"Metaclass=> <class '__main__.PolygonType'> Triangle\n",
608-
"Attaching function <function triangle_valid at 0x7fb57443e400> as is_valid method\n"
619+
"Attaching function <function triangle_valid at 0x7f94781d3730> as is_valid method\n"
609620
]
610621
}
611622
],

0 commit comments

Comments
 (0)