Guest User

Untitled

a guest
Nov 12th, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.88 KB | None | 0 0
  1. {
  2. "cells": [
  3. {
  4. "metadata": {},
  5. "cell_type": "markdown",
  6. "source": "# Table of content\n* [List Slices](#slice)\n* [List Comprehension](#compre)\n* [Lambda](#lambda)\n* [Map, Filter & Reduce](#map)\n* [Decorator](#dec)\n* [Class](#class)\n* [Iterable, Iterator and Generator](#iter-gen) (optional but recommended to read)"
  7. },
  8. {
  9. "metadata": {},
  10. "cell_type": "markdown",
  11. "source": "# List Slices <a name=\"slice\"></a>\n\n__List slices__ provides an advanced way of retrieving values from a list. Basic list slicing involves indexing a list with __two colon-separated integers__. These three arguments are lower limit, upper limit and step. This returns a new list containing all the values in the old list between the indices specified. By default, lower limit is at index 0, upper limit is at the last value and step is +1. \n\nYou can also take a step backwards. When __negative values__ are used for the first and second values in a slice, they __count from the end of list__.\n\n__NOTE__: Slicing can also be done on __tuple__."
  12. },
  13. {
  14. "metadata": {
  15. "ExecuteTime": {
  16. "end_time": "2018-11-13T02:12:03.418825Z",
  17. "start_time": "2018-11-13T02:12:03.407403Z"
  18. },
  19. "trusted": true
  20. },
  21. "cell_type": "code",
  22. "source": "squares = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n\nprint(squares[:])\nprint(squares[::2])\nprint(squares[2:8:2])\nprint(squares[6:])\nprint(squares[4:14])\nprint(squares[1:-2])\nprint(squares[7:1:-2])\nprint(squares[::-1])",
  23. "execution_count": 1,
  24. "outputs": [
  25. {
  26. "name": "stdout",
  27. "output_type": "stream",
  28. "text": "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n[0, 4, 16, 36, 64]\n[4, 16, 36]\n[36, 49, 64, 81]\n[16, 25, 36, 49, 64, 81]\n[1, 4, 9, 16, 25, 36, 49]\n[49, 25, 9]\n[81, 64, 49, 36, 25, 16, 9, 4, 1, 0]\n"
  29. }
  30. ]
  31. },
  32. {
  33. "metadata": {},
  34. "cell_type": "markdown",
  35. "source": "# List Comprehension <a name=\"compre\"></a>\n\nList comprehension is a useful way of quickly creating lists using simplified version of _for_ loop statement. A list comprehension __can also contain an if statement__ to enforce a condition on values in the list.\n\n__NOTE__: Trying to create a list, by any means, in a very extensive range will result in a __MemoryError__.\n\n```\nvar = [2*i for i in range(10**100)]\n```\n\n### DON'T EVEN TRY IT!"
  36. },
  37. {
  38. "metadata": {
  39. "ExecuteTime": {
  40. "end_time": "2018-11-13T02:12:03.603066Z",
  41. "start_time": "2018-11-13T02:12:03.460128Z"
  42. },
  43. "trusted": true
  44. },
  45. "cell_type": "code",
  46. "source": "evens=[i**2 for i in range(10) if i**2 % 2 == 0]\nprint(evens)",
  47. "execution_count": 2,
  48. "outputs": [
  49. {
  50. "name": "stdout",
  51. "output_type": "stream",
  52. "text": "[0, 4, 16, 36, 64]\n"
  53. }
  54. ]
  55. },
  56. {
  57. "metadata": {},
  58. "cell_type": "markdown",
  59. "source": "# Lamda <a name=\"lambda\"></a>\n\nIn Python, __anonymous function__ means a function __without a name__, whereas we use _def_ keyword to create normal functions. The __lambda__ function is used for creating _small, one-time and anonymous_ function objects in Python. The lambda operator can have __any number of arguments__, but it can have __only one expression__. The lambda functions can be assigned to variables, and used like normal functions.\n\nUse lambda functions when an anonymous function is required for a short period of time."
  60. },
  61. {
  62. "metadata": {
  63. "ExecuteTime": {
  64. "end_time": "2018-11-13T02:12:03.716686Z",
  65. "start_time": "2018-11-13T02:12:03.606551Z"
  66. },
  67. "trusted": true
  68. },
  69. "cell_type": "code",
  70. "source": "#named function\ndef polynomial(x):\n '''\n Function to perform a polynomial calculation having a single variable x\n '''\n return x**2 + 5*x + 4\n\nprint(\"The result for named function: {}\".format(polynomial(-4)))\n\n\n#lambda\npoly = lambda x: x**2 + 5*x + 4\nprint(\"The result for anonymous function: {}\".format(poly(-4)))",
  71. "execution_count": 3,
  72. "outputs": [
  73. {
  74. "name": "stdout",
  75. "output_type": "stream",
  76. "text": "The result for named function: 0\nThe result for anonymous function: 0\n"
  77. }
  78. ]
  79. },
  80. {
  81. "metadata": {},
  82. "cell_type": "markdown",
  83. "source": "# Map, Filter & Reduce <a name=\"map\"></a>\n\nThe built-in functions __map__, __filter__ and __reduce__ are very useful higher-order functions that operate on iterable. \n\nThe function __map__ takes a function and an iterable as _arguments_, and returns a _new iterable_ with the function applied to each argument.\n\nThe function __filter__ filters an iterable by removing items that don't match a __predicate (a function that returns ONLY Boolean True)__.\n\nThe function __reduce__ applies a rolling computation to sequential pairs of values in a iterable i.e., wanted to compute the product of a list items, sum of tuple items.\n\n__NOTE__: Both in map and filter, the result has to be explicitly converted to a list or tuple if you want to print it. Python 2 returns a list by default, but this was changed in Python 3 which returns map or filter object, hence the need for the list or tuple function."
  84. },
  85. {
  86. "metadata": {
  87. "ExecuteTime": {
  88. "end_time": "2018-11-13T02:12:03.897942Z",
  89. "start_time": "2018-11-13T02:12:03.720605Z"
  90. },
  91. "trusted": true
  92. },
  93. "cell_type": "code",
  94. "source": "def add_five(x):\n return x + 5\n\nnum_var = [11, 22, 33, 44, 55]\nmap_result = list(map(add_five, num_var)) # map\nprint(map_result)\n\nfilter_result = tuple(filter(lambda x: x%2==0, num_var)) # filter\nprint(filter_result)\n\nfrom functools import reduce\nreduce_result = reduce((lambda x, y: x*y), num_var) # reduce\nprint(reduce_result)",
  95. "execution_count": 4,
  96. "outputs": [
  97. {
  98. "name": "stdout",
  99. "output_type": "stream",
  100. "text": "[16, 27, 38, 49, 60]\n(22, 44)\n19326120\n"
  101. }
  102. ]
  103. },
  104. {
  105. "metadata": {},
  106. "cell_type": "markdown",
  107. "source": "__Small task__\n\n* Do the same thing shown above in filter code using list comprehension.\n* Solve this:\n\n```\nres = tuple(map(lambda x: x%2==0,num_var))\n```"
  108. },
  109. {
  110. "metadata": {},
  111. "cell_type": "markdown",
  112. "source": "__Exercise__: Take a n digit (n > 4) number as user input and generate a single digit output by successively adding the digits of the integer."
  113. },
  114. {
  115. "metadata": {
  116. "ExecuteTime": {
  117. "end_time": "2018-11-13T02:12:07.187431Z",
  118. "start_time": "2018-11-13T02:12:03.902454Z"
  119. },
  120. "hide_input": true,
  121. "trusted": true
  122. },
  123. "cell_type": "code",
  124. "source": "num = int(input(\"Enter a number (More than 4 digit number): \"))\nwhile len(str(num))!= 1:\n num_lst = [int(i) for i in str(num)]\n num = reduce((lambda x, y: x+y), num_lst)\n \nprint(num)",
  125. "execution_count": 5,
  126. "outputs": [
  127. {
  128. "name": "stdout",
  129. "output_type": "stream",
  130. "text": "Enter a number (More than 4 digit number): 785234\n2\n"
  131. }
  132. ]
  133. },
  134. {
  135. "metadata": {
  136. "ExecuteTime": {
  137. "end_time": "2018-11-13T02:12:07.198080Z",
  138. "start_time": "2018-11-13T02:12:07.190788Z"
  139. },
  140. "trusted": true
  141. },
  142. "cell_type": "code",
  143. "source": "# what do you think is the output?\nmylist = [1,2,3,4,5]\n\nprint(tuple(map(lambda x: x if x>1 else 0, mylist)))\nprint(list(filter(lambda x: x if x>1 else 0, mylist)))",
  144. "execution_count": 6,
  145. "outputs": [
  146. {
  147. "name": "stdout",
  148. "output_type": "stream",
  149. "text": "(0, 2, 3, 4, 5)\n[2, 3, 4, 5]\n"
  150. }
  151. ]
  152. },
  153. {
  154. "metadata": {},
  155. "cell_type": "markdown",
  156. "source": "# Decorator <a name=\"dec\"></a>\n\n__Decorator__ are functions which modify the functionality of another function. Let's go one step at a time to understand decorator. In the beginner's article, we have mentioned that Python's function is a __first class object__ which can be\n* dynamically created, destroyed\n* stored in a variable\n* passed to a function as a parameter\n* returned as a value from a function\n\nWe have already seen the first point to be valid in the beginner's article. Let's validate each of these remaining 3 point."
  157. },
  158. {
  159. "metadata": {
  160. "ExecuteTime": {
  161. "end_time": "2018-11-13T02:12:07.422834Z",
  162. "start_time": "2018-11-13T02:12:07.203055Z"
  163. },
  164. "trusted": true
  165. },
  166. "cell_type": "code",
  167. "source": "## functions can be assigned to a variable\n\ndef my_pymon(text): \n return \"Let's go, {}\".format(text.upper())\n\ni_choose_you = my_pymon\nprint(i_choose_you('pykachu'))\n\nprint(\"=\"*20)\n\n## functions can be passed as argument to another function\n\ndef your_pymon(text):\n return f\"{text}\"\n\ndef trainer_select(func):\n print(func(\"I choose you, 'char'mander\"))\n \ntrainer_select(your_pymon)\n\nprint(\"=\"*20)\n\n## function returned as a value from another function\n\ndef battle_began_with(mons):\n def who_won(someone):\n return f\"In the battle, {someone} won against {mons}\"\n return who_won\n\nbattle = battle_began_with(\"'char'mander\")(\"pykachu\")\nprint(battle)",
  168. "execution_count": 7,
  169. "outputs": [
  170. {
  171. "name": "stdout",
  172. "output_type": "stream",
  173. "text": "Let's go, PYKACHU\n====================\nI choose you, 'char'mander\n====================\nIn the battle, pykachu won against 'char'mander\n"
  174. }
  175. ]
  176. },
  177. {
  178. "metadata": {
  179. "ExecuteTime": {
  180. "end_time": "2018-11-13T02:12:07.559081Z",
  181. "start_time": "2018-11-13T02:12:07.426901Z"
  182. },
  183. "trusted": true
  184. },
  185. "cell_type": "code",
  186. "source": "## let's explore more with this \"Marvel\"lous example\n\ndef vision(var = \"Vision\"):\n print(var+\" is not only a representation of Mind Stone!\")\n def tony():\n return \"Yeah! I'm there.\"\n def banner():\n return \"I know I'm there too, but what happened with Hulk?\"\n def mindstone():\n return \"What are we even discussing?\"\n \n print(\"Tony: \",tony())\n print(\"Banner: \",banner())\n print(\"Mind Stone: \",mindstone)\n print(var,\": Enough! I died, came back to life to be killed again! -_-\")\n \nvision()",
  187. "execution_count": 8,
  188. "outputs": [
  189. {
  190. "name": "stdout",
  191. "output_type": "stream",
  192. "text": "Vision is not only a representation of Mind Stone!\nTony: Yeah! I'm there.\nBanner: I know I'm there too, but what happened with Hulk?\nMind Stone: <function vision.<locals>.mindstone at 0x7f45b05dda60>\nVision : Enough! I died, came back to life to be killed again! -_-\n"
  193. }
  194. ]
  195. },
  196. {
  197. "metadata": {},
  198. "cell_type": "markdown",
  199. "source": "__When you put the pair of parentheses after the function name in main of code, only then the function gets executed. If you don’t put parentheses after it, then it can be passed around and can be assigned to other variables without executing it.__"
  200. },
  201. {
  202. "metadata": {
  203. "ExecuteTime": {
  204. "end_time": "2018-11-13T02:12:07.700135Z",
  205. "start_time": "2018-11-13T02:12:07.565539Z"
  206. },
  207. "trusted": true
  208. },
  209. "cell_type": "code",
  210. "source": "def my_decor(a_func):\n\n def wrapper_func():\n print(\"I am doing some boring work before executing a_func()\")\n a_func()\n print(\"I am doing some boring work after executing a_func()\")\n\n return wrapper_func\n\ndef a_function_requiring_decor():\n print(\"I am the function which needs some decoration!\")\n \nprint(a_function_requiring_decor())\n\nprint(\"=\"*50)\n\na_function_requiring_decor = my_decor(a_function_requiring_decor) #the so-called decorator is happening here\nprint(a_function_requiring_decor())",
  211. "execution_count": 9,
  212. "outputs": [
  213. {
  214. "name": "stdout",
  215. "output_type": "stream",
  216. "text": "I am the function which needs some decoration!\nNone\n==================================================\nI am doing some boring work before executing a_func()\nI am the function which needs some decoration!\nI am doing some boring work after executing a_func()\nNone\n"
  217. }
  218. ]
  219. },
  220. {
  221. "metadata": {},
  222. "cell_type": "markdown",
  223. "source": "The variable __a_function_requiring_decor__ is pointing to the __wrapper_func__ inner function. We are __returning wrapper_func as a function__ when we call __my_decor(a_function_requiring_decor)__. So, __decorator wraps a function, modifying its behavior__.\n\nAnother way to write these decorators is using __\"pie\" syntax, using @ symbol__."
  224. },
  225. {
  226. "metadata": {
  227. "ExecuteTime": {
  228. "end_time": "2018-11-13T02:12:07.833876Z",
  229. "start_time": "2018-11-13T02:12:07.702754Z"
  230. },
  231. "trusted": true
  232. },
  233. "cell_type": "code",
  234. "source": "def my_decorator(func):\n def wrapper():\n print(\"Take the marker and write something on the board.\")\n func()\n print(\"Well done!\")\n return wrapper\n\n@my_decorator\ndef tricky():\n print(\"SOMETHING!\")\n \ntricky()",
  235. "execution_count": 10,
  236. "outputs": [
  237. {
  238. "name": "stdout",
  239. "output_type": "stream",
  240. "text": "Take the marker and write something on the board.\nSOMETHING!\nWell done!\n"
  241. }
  242. ]
  243. },
  244. {
  245. "metadata": {},
  246. "cell_type": "markdown",
  247. "source": "# Class <a name=\"class\"></a>\n\nPython is an _object-oriented programming_ (OOP) language and objects are created using __class__ which is actually the focal point of OOP. The class describes an object's blueprint, description or metadata. Multiple object can be instantiated using the _same class_.\n\nClasses are created using the keyword __class__ and an indented block, which contains class _methods_.\n\nLet's take a look at an example."
  248. },
  249. {
  250. "metadata": {
  251. "ExecuteTime": {
  252. "end_time": "2018-11-13T02:12:07.976210Z",
  253. "start_time": "2018-11-13T02:12:07.837076Z"
  254. },
  255. "trusted": true
  256. },
  257. "cell_type": "code",
  258. "source": "class Pet:\n def __init__(self, genre, name, owner):\n self.genre = genre \n self.name = name\n self.owner = owner\n \n def voice(self): #another method added to the class Pet\n print(\"Growl!\")\n \npokemon = Pet(\"dog\",\"Arcanine\",\"Tim\")\nprint(pokemon.name)\npokemon.voice()",
  259. "execution_count": 11,
  260. "outputs": [
  261. {
  262. "name": "stdout",
  263. "output_type": "stream",
  264. "text": "Arcanine\nGrowl!\n"
  265. }
  266. ]
  267. },
  268. {
  269. "metadata": {},
  270. "cell_type": "markdown",
  271. "source": "The **__ init__** method is the most important method in a class which is called when an instance (object) of the class is created. __All methods must have self as their first parameter__, although you do not need to pass it explicitly when you call the method.\n\nWithin the method definition, __self__ refers to the object itself calling the method. From the above example, we see that\n\n```\npokemon = Pet(\"dog\",\"Arcanine\",\"Tim\")\nprint(pokemon.name)\n>>> Arcanine\n```\n\n* When we create the pokemon object from the class Pet, we are passing _genre, name and owner_ as \"dog\",\"Arcanine\",\"Tim\" and the object (pokemon) will take the place of self.\n* The attributes are accessed using the __dot__ operator.\n* So __pokemon is the object__, \"_Arcanine_\" is the value of the __name__ attribute of this object. \n\nHence, we can access the attributes in a class using this way: __object.attributes__.\n\nClasses can have other methods defined to add functionality to them. These methods are accessed using the same dot syntax as attributes.\n\n__NOTE__: All methods __must have self__ as their first parameter.\n\nTrying to access an attribute of an instance that isn't defined causes an __AttributeError__."
  272. },
  273. {
  274. "metadata": {},
  275. "cell_type": "markdown",
  276. "source": "# Iterable, Iterator and Generator <a name=\"iter-gen\"></a>\n\n## Iterable and Iterator\n\nIteration -> Repetition of a process.\n\n__Iterable__ is a type of object which would __generate an Iterator__ when passed to in-built method __iter()__.\n\n__Iterator__ is an object which is used to iterate over an _iterable object_ using __next__() method, which returns the next item of the _iterable object_. Any object that has a __next__() method is therefore an iterator.\n\n__NOTE__: List, Tuple, Set, Frozenset, Dictionary are in-built __iterable objects__. They are __iterable containers__ from which you can get an __iterator__."
  277. },
  278. {
  279. "metadata": {
  280. "ExecuteTime": {
  281. "end_time": "2018-11-13T02:12:08.127343Z",
  282. "start_time": "2018-11-13T02:12:07.979739Z"
  283. },
  284. "trusted": true
  285. },
  286. "cell_type": "code",
  287. "source": "## Let's see an example\nmy_tuple = [\"apple\", \"banana\", \"cherry\"]\niterated_tuple = iter(my_tuple)\n\nprint(type(iterated_tuple))\nprint(next(iterated_tuple))\nprint(next(iterated_tuple))\nprint(next(iterated_tuple))",
  288. "execution_count": 12,
  289. "outputs": [
  290. {
  291. "name": "stdout",
  292. "output_type": "stream",
  293. "text": "<class 'list_iterator'>\napple\nbanana\ncherry\n"
  294. }
  295. ]
  296. },
  297. {
  298. "metadata": {
  299. "ExecuteTime": {
  300. "end_time": "2018-11-13T02:12:08.245412Z",
  301. "start_time": "2018-11-13T02:12:08.129778Z"
  302. },
  303. "trusted": true
  304. },
  305. "cell_type": "code",
  306. "source": "## same thing can be written using for loop\nmy_tuple = (\"apple\", \"banana\", \"cherry\")\n\nfor i in my_tuple:\n print(i)",
  307. "execution_count": 13,
  308. "outputs": [
  309. {
  310. "name": "stdout",
  311. "output_type": "stream",
  312. "text": "apple\nbanana\ncherry\n"
  313. }
  314. ]
  315. },
  316. {
  317. "metadata": {},
  318. "cell_type": "markdown",
  319. "source": "**How for loop actually works?**\n\nThe for loop can iterate over any iterable. \n\n```\nfor element in iterable:\n # do something with element\n```\n\nis actually implemented as\n\n```\n# create an iterator object from that iterable\niter_obj = iter(iterable)\n\n# infinite loop\nwhile True:\n try:\n # get the next item\n element = next(iter_obj)\n # do something with element\n except StopIteration:\n # if StopIteration is raised, break from loop\n break\n```\n\n* The for loop creates an iterator object internally, __iter_obj__ by calling _iter()_ on the iterable.\n* Inside the __while loop__, it calls _next()_ to get the next element and executes further\n* After all the items exhaust, __StopIteration__ exception is raised which is internally caught and the loop ends.\n\nTo get a better sense of the internals of an iterator, let's build an iterator producing the __Fibonacci numbers__."
  320. },
  321. {
  322. "metadata": {
  323. "ExecuteTime": {
  324. "end_time": "2018-11-13T02:12:08.395122Z",
  325. "start_time": "2018-11-13T02:12:08.250693Z"
  326. },
  327. "trusted": true
  328. },
  329. "cell_type": "code",
  330. "source": "from itertools import islice\n\nclass fib:\n def __init__(self):\n self.prev = 0\n self.curr = 1\n \n def __iter__(self):\n return self\n \n def __next__(self):\n value = self.curr\n self.curr += self.prev\n self.prev = value\n return value\n\nf = fib()\nprint(list(islice(f, 0, 10)))",
  331. "execution_count": 14,
  332. "outputs": [
  333. {
  334. "name": "stdout",
  335. "output_type": "stream",
  336. "text": "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]\n"
  337. }
  338. ]
  339. },
  340. {
  341. "metadata": {},
  342. "cell_type": "markdown",
  343. "source": "## Generator\n\nA lot of overhead in building an iterator:\n* implement a class with iter() and next() methods\n* raise StopIteration when there was no values to be returned\n* makes the code lengthy\n\nPython Generators are a simple way of creating iterators. All the above mentioned overhead are automatically handled by generators in Python.\n\n__Generator__ is a block of code, same as defining a function, having a __yield__ statement instead of a __return__ statement.\n\nIf a function contains **at least one yield** statement (it may contain other yield or return statements), it becomes a generator!\n\nThis is how the above Fibonacci number code looks like using generator."
  344. },
  345. {
  346. "metadata": {
  347. "ExecuteTime": {
  348. "end_time": "2018-11-13T02:12:08.517831Z",
  349. "start_time": "2018-11-13T02:12:08.398265Z"
  350. },
  351. "trusted": true
  352. },
  353. "cell_type": "code",
  354. "source": "def fib():\n prev, curr = 0, 1\n while True:\n yield curr\n prev, curr = curr, prev + curr\n\nf = fib()\nprint(list(islice(f, 0, 10)))",
  355. "execution_count": 15,
  356. "outputs": [
  357. {
  358. "name": "stdout",
  359. "output_type": "stream",
  360. "text": "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]\n"
  361. }
  362. ]
  363. },
  364. {
  365. "metadata": {},
  366. "cell_type": "markdown",
  367. "source": "### Let's see what happened.\n\nTake note that __fib__ is defined as a normal Python function, not as class. However, there's __no return keyword__ inside the function body. __The return value of the function will be a generator__.\n\n1. Now when __f = fib()__ is called, the generator is instantiated and returned. __No code will be executed__ at this point.To be explicit: the line prev, curr = 0, 1 is not executed yet.\n\n2. Then, this generator instance is wrapped in an islice(). This is itself also an iterator. Again, no code executed.\n\n3. Now, this iterator is wrapped in a __list()__, which will take the argument and build a list from it. To do so, it will start calling next() on the islice() instance, which in turn will start calling next() on our f instance.\n\n4. On the first call, the code __prev, curr = 0, 1__ gets executed, then the __while True__ loop is entered, and then it encounters the __yield curr__ statement. It will produce the value that's currently in the _curr_ variable and become idle again. This value is passed to the _islice()_ wrapper, which will produce the value (1 in this case) and list can add the value to the list.\n\n5. Then, list asks islice() for the next value, which will ask f for the next value, which will _unpause_ f from its previous state, resuming with the statement __prev, curr = curr, prev + curr__. \n\n6. Then it re-enters the next iteration of the __while True__ loop, and hits the __yield curr__ statement, returning the next value of curr.\n\n7. This happens until the output list is 10 elements long. When list() asks islice() for the 11th value, islice() will raise a __StopIteration__ exception, indicating that the end has been reached, and list will return the result: a list of 10 items, containing the first 10 Fibonacci numbers.\n\nThere are two types of generators in Python: __generator functions__ and __generator expressions__. A generator function is any function in which the keyword __yield__ appears in its body. We just saw an example of that. Generator expression is equivalent to list comprehension."
  368. }
  369. ],
  370. "metadata": {
  371. "kernelspec": {
  372. "name": "python3",
  373. "display_name": "Python 3",
  374. "language": "python"
  375. },
  376. "language_info": {
  377. "name": "python",
  378. "version": "3.6.6",
  379. "mimetype": "text/x-python",
  380. "codemirror_mode": {
  381. "name": "ipython",
  382. "version": 3
  383. },
  384. "pygments_lexer": "ipython3",
  385. "nbconvert_exporter": "python",
  386. "file_extension": ".py"
  387. },
  388. "gist": {
  389. "id": "",
  390. "data": {
  391. "description": "Python Notebook | Intermediate | Part 2.ipynb",
  392. "public": true
  393. }
  394. }
  395. },
  396. "nbformat": 4,
  397. "nbformat_minor": 2
  398. }
Add Comment
Please, Sign In to add comment