Skip to content

Commit a9215c1

Browse files
committed
W5: Begin intermission on decorators
1 parent 74ad47b commit a9215c1

File tree

1 file changed

+130
-10
lines changed

1 file changed

+130
-10
lines changed

week5/w5.ipynb

Lines changed: 130 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@
376376
"We're repeating the code for the constructor, introduce and, eat. The main difference is the profession specific method!\n",
377377
"What if we want to change how a person should be introduced? We'd have to update the `introduce` method in `Person`, `ComputerScientist`, `Doctor`.\n",
378378
"\n",
379-
"We can use *inheritance* to simplify our code, improve its maintainability, reduce development costs (avoids the scenario above which could introduce bugs!),\n",
379+
"We can use *inheritance* to improve its maintainability, reduce development costs (avoids the scenario above which could introduce bugs!),\n",
380380
"and avoid repeating code."
381381
]
382382
},
@@ -465,27 +465,147 @@
465465
"cell_type": "markdown",
466466
"metadata": {},
467467
"source": [
468-
"**[INSERT diagram for class vs object]**"
468+
"### Intermission: Decorators\n",
469+
"Before we continue exploring object-oriented programming, let's have a look at decorators.\n",
470+
"\n",
471+
"Congratulations, you've just been hired by the *National X-Soc Co-op Bank Ltd* to develop their ATM system!\n",
472+
"\n",
473+
"They want you to implement the depositing and withdrawal functionality and you define the\n",
474+
"functions `deposit_monies` and `withdraw_monies`.\n",
475+
"These operations are, of course, very sensitive, so you check if the username matches\n",
476+
"the username of the authorised personnel."
477+
]
478+
},
479+
{
480+
"cell_type": "code",
481+
"execution_count": null,
482+
"metadata": {},
483+
"outputs": [],
484+
"source": [
485+
"def deposit_monies(user):\n",
486+
" if user not in {\"admin\", \"important_banker\"}:\n",
487+
" print(\"Unauthorised!\")\n",
488+
" return\n",
489+
" \n",
490+
" print(f\"Brrr brr very important operation. Depositing $44b into an account\")\n",
491+
"\n",
492+
"def withdraw_monies(user):\n",
493+
" if user not in {\"admin\", \"important_banker\"}:\n",
494+
" print(\"Unauthorised!\")\n",
495+
" return\n",
496+
" \n",
497+
" print(f\"Brrr brr very important operation. Withdrawing $44b from an account\")\n",
498+
"\n",
499+
"withdraw_monies(\"admin\")\n",
500+
"withdraw_monies(\"donald knuth\")\n",
501+
"\n",
502+
"deposit_monies(\"admin\")\n",
503+
"deposit_monies(\"donald knuth\")"
469504
]
470505
},
471506
{
472507
"cell_type": "markdown",
473508
"metadata": {},
474509
"source": [
475-
"TBD:\n",
476-
"- polymorphism/abstraction/encapsulation a little bit\n",
477-
"- attributes (class and instance atttr)\n",
478-
"- inheritance example\n",
479-
"- then intermission on anotations\n",
480-
"- static and class methods"
510+
"However, after an FCA audit, the auditors notice that the authorisation code is repeated in each operation.\n",
511+
"If we want to update our authorisation scheme, we'd have to update the code of every operation. This is error prone and could introduce vulnerabilities into the ATM system\n",
512+
"so the FCA asked the *National X-Soc Co-op Bank Ltd* to investigate this issue.\n",
513+
"\n",
514+
"We could start, by introducing a function which \"adds\" this authorisation code before an operation.\n",
515+
"As we've learned, **everything** in Python is an object, including functions, so you can pass a function\n",
516+
"as an argument of a function or even return a function!\n",
517+
"\n",
518+
"Essentially, we define a function, which will return another function. The new function\n",
519+
"checks if the user is authorised, and if the user is authorised, we execute the operation!"
520+
]
521+
},
522+
{
523+
"cell_type": "code",
524+
"execution_count": null,
525+
"metadata": {},
526+
"outputs": [],
527+
"source": [
528+
"def requires_authorisation(operation):\n",
529+
" def secure_operation(user):\n",
530+
" if user not in {\"admin\", \"important_banker\"}:\n",
531+
" print(\"Unauthorised!\")\n",
532+
" return\n",
533+
" \n",
534+
" operation(user)\n",
535+
"\n",
536+
" return secure_operation\n",
537+
"\n",
538+
"def deposit_monies(user):\n",
539+
" print(f\"Brrr brr very important operation. Depositing $44b into an account\")\n",
540+
"\n",
541+
"def withdraw_monies(user):\n",
542+
" print(f\"Brrr brr very important operation. Withdrawing $44b from an account\")\n",
543+
"\n",
544+
"\n",
545+
"secure_withdraw_monies = requires_authorisation(withdraw_monies)\n",
546+
"\n",
547+
"secure_withdraw_monies(\"admin\")\n",
548+
"secure_withdraw_monies(\"donald knuth\")\n",
549+
"\n",
550+
"secure_deposit_monies = requires_authorisation(deposit_monies)\n",
551+
"\n",
552+
"secure_deposit_monies(\"admin\")\n",
553+
"secure_deposit_monies(\"donald knuth\")"
481554
]
482555
},
483556
{
484557
"cell_type": "markdown",
485558
"metadata": {},
486559
"source": [
487-
"### Intermission: Decorators\n",
488-
"Before we continue exploring classes...\n"
560+
"However, we can go one step further and make our code a bit nicer with *syntatic sugar*"
561+
]
562+
},
563+
{
564+
"cell_type": "code",
565+
"execution_count": null,
566+
"metadata": {},
567+
"outputs": [],
568+
"source": [
569+
"def requires_authorisation(operation):\n",
570+
" def secure_operation(user):\n",
571+
" if user not in {\"admin\", \"important_banker\"}:\n",
572+
" print(\"Unauthorised!\")\n",
573+
" return\n",
574+
" \n",
575+
" operation(user)\n",
576+
"\n",
577+
" return secure_operation\n",
578+
"\n",
579+
"@requires_authorisation\n",
580+
"def deposit_monies(user):\n",
581+
" print(f\"Brrr brr very important operation. Depositing $44b into an account\")\n",
582+
"\n",
583+
"@requires_authorisation\n",
584+
"def withdraw_monies(user):\n",
585+
" print(f\"Brrr brr very important operation. Withdrawing $44b from an account\")\n",
586+
"\n",
587+
"withdraw_monies(\"admin\")\n",
588+
"withdraw_monies(\"donald knuth\")\n",
589+
"\n",
590+
"deposit_monies(\"admin\")\n",
591+
"deposit_monies(\"donald knuth\")"
592+
]
593+
},
594+
{
595+
"cell_type": "markdown",
596+
"metadata": {},
597+
"source": [
598+
"**[INSERT diagram for class vs object]**"
599+
]
600+
},
601+
{
602+
"cell_type": "markdown",
603+
"metadata": {},
604+
"source": [
605+
"TBD:\n",
606+
"- polymorphism/abstraction/encapsulation a little bit\n",
607+
"- then intermission on anotations\n",
608+
"- static and class methods"
489609
]
490610
},
491611
{

0 commit comments

Comments
 (0)