Python Programming: What NOT To Do

Python
What NOT To Do
The stereotype
Side effect
It’s way too easy to write code that works.
Example: 
for
 loop
basket = [
'Apples'
, 
'Oranges'
, 
'Bananas'
]
for 
i 
in 
range
(
len
(basket)):
   
print
(basket[i])
basket = [
'Apples'
, 
'Oranges'
, 
'Bananas'
]
for 
item 
in 
basket:
   
print
(item)
Example: 
for
 loop with index
 
basket = [
'Apples'
, 
'Oranges'
, 
'Bananas'
]
for 
i 
in 
range
(
len
(basket)):
   
print
(
'{}. {}'
.format(i
, 
basket
[i]))
basket = [
'Apples'
, 
'Oranges'
, 
'Bananas'
]
for 
i
, 
item 
in 
enumerate
(
basket
):
   
print
(
'{}. {}'
.format(i
, 
item))
Learning Python the easy way
Understand Python is easy
Write a lot of
code fast
Blame Python
for being
unreadable
Success!
The solution
1.
Learn how to do things in a “pythonic” way.
2.
Learn what NOT to do.
Tip #1
Google even the simplest things using this phrase:
Tip #2
Read “The Little Book of Python Anti-Patterns”
Tip #3
Stay for the rest of this talk 
☺️
Agenda
1.
Suppressing exceptions
Less obvious ways of ruining your life than 
except 
Exception
1.
Enabling warnings globally
How to mess up everyone's logs in an obscure fashion.
Exceptions
The ultimate sin
try
:
   do_something()
except
:
   do_something_else()
This is almost just as bad
try
:
   do_something()
except 
Exception
:
   do_something_else()
This forces others to sin
raise 
Exception
(
'Bad stuff happened!'
)
But there’s more...
class 
FridgeError(
Exception
):
   
pass
class 
Fridge(
object
):
   
def 
open
(
self
):
       
raise 
FridgeError(
'Broken Fridge'
)
   
def 
close
(
self
):
       
pass
   def 
__iter__
(
self
):
       
pass
def 
collect_fruits
(fridge):
   fruits = []
   
try
:
       fridge.open()
       
for 
shelf 
in 
fridge:
           fruits += shelf.fruits
   
finally
:
       fridge.close()
       
return 
fruits
collect_fruits(Fridge())
class 
FridgeError(
Exception
):
   
pass
class 
Fridge(
object
):
   
def 
open
(
self
):
       
raise 
FridgeError(
'Broken Fridge'
)
   
def 
close
(
self
):
       
pass
   def 
__iter__
(
self
):
       
pass
def 
collect_fruits
(fridge):
   fruits = []
   
try
:
       fridge.open()
       
for 
shelf 
in 
fridge:
           fruits += shelf.fruits
   
finally
:
       fridge.close()
   
return 
fruits
collect_fruits(Fridge())
Traceback (most recent call last):
  File "
main.py
", line 61, in <module>
    collect_fruits(Fridge())
  File "
main.py
", line 53, in collect_fruits
    fridge.open()
  File "
main.py
", line 41, in open
    raise FridgeError('Broken Fridge')
__main__.FridgeError: Broken Fridge
Why does this happen?
A function can either 
return 
a value or 
raise 
an
exception, it cannot do both.
How to avoid it and live a happy life?
Do not return anything in 
finally
:
 block.
Warnings
Food package
import 
warnings
class 
ArsenicWarning(
UserWarning
):
   
pass
class 
Arsenic(
object
):
   
def 
__init__
(
self
):
       warnings.warn(
'This product is poisonous!'
,
                     
ArsenicWarning)
from 
additives 
import 
Arsenic
class 
Orange(
object
):
   
def 
__init__
(
self
):
       
self
.content = Arsenic()
additives.py
fruits.py
> python main.py
/food/additives.py:11: ArsenicWarning: This product is poisonous!
  warnings.warn('This product is poisonous!', ArsenicWarning)
from 
food.fruits 
import 
Orange
my_orange = Orange()
Food package
import 
warnings
class 
ArsenicWarning(
UserWarning
):
   
pass
class 
Arsenic(
object
):
   
def 
__init__
(
self
):
       warnings.warn(
'This product is poisonous!'
,
                     
ArsenicWarning)
import 
warnings
from 
additives 
import 
Arsenic
warnings.filterwarnings(
'ignore'
)
class 
Orange(
object
):
   
def 
__init__
(
self
):
       
self
.content = Arsenic()
additives.py
fruits.py
> python main.py
Process finished with exit code 0
from 
food.fruits 
import 
Orange
my_orange = Orange()
Food package
class 
OldTomato(
object
):
   
def 
__init__
(
self
):
       
pass
vegetables.py
Food package
import 
warnings
class 
Tomato(
object
):
   
def 
__init__
(
self
):
       
pass
def 
OldTomato
():
   warnings.warn(
'Deprecated! Use Tomato instead!'
,
                 
DeprecationWarning
)
vegetables.py
> python main.py
Process finished with exit code 0
from 
food.vegetables 
import 
OldTomato
my_tomato = OldTomato()
Food package
import 
warnings
warnings.filterwarnings(
"always"
)
class 
Tomato(
object
):
   
def 
__init__
(
self
):
       
pass
def 
OldTomato
():
   warnings.warn(
'Deprecated! Use Tomato instead!'
,
                 
DeprecationWarning
)
vegetables.py
> python main.py
/food/vegetables.py:13: DeprecationWarning: Deprecated! Use Tomato instead!
  warnings.warn('Deprecated! Use Tomato instead!', DeprecationWarning)
from 
food.vegetables 
import 
OldTomato
my_tomato = OldTomato()
> python main.py
Process finished with exit code 0
from 
food.vegetables 
import 
OldTomato
from 
food.fruits 
import 
Orange
my_tomato = OldTomato()
my_orange = Orange()
> python main.py
/food/vegetables.py:13: DeprecationWarning: Deprecated! Use Tomato instead!
  warnings.warn('Deprecated! Use Tomato instead!', DeprecationWarning)
/food/additives.py:11: ArsenicWarning: This product is poisonous!
  warnings.warn('This product is poisonous!', ArsenicWarning)
from 
food.fruits 
import 
Orange
from 
food.vegetables 
import 
OldTomato
my_tomato = OldTomato()
my_orange = Orange()
Why does this happen?
warnings.filterwarnings
 manages warnings
globally, so it’s possible to affect warnings outside
current module.
How to avoid it and live a happy life?
If possible - do not do it on library level and let
the user control warnings in his own code.
How to avoid it and live a happy life?
If you absolutely need to - at least be precise.
Food package
import 
warnings
class 
ArsenicWarning(
UserWarning
):
   
pass
class 
Arsenic(
object
):
   
def 
__init__
(
self
):
       warnings.warn(
'This product is poisonous!'
,
                     
ArsenicWarning)
import 
warnings
from 
additives 
import 
Arsenic, ArsenicWarning
warnings.filterwarnings(
'ignore'
,
                        
category
=ArsenicWarning
,
                        
module
=
'food.additives'
)
class 
Orange(
object
):
   
def 
__init__
(
self
):
       
self
.content = Arsenic()
additives.py
fruits.py
Food package
import 
warnings
warnings.filterwarnings(
'always'
,
                        category
=
DeprecationWarning
,
                        
module
=__name__)
class 
Tomato(
object
):
   
def 
__init__
(
self
):
       
pass
def 
OldTomato
():
   warnings.warn(
'Deprecated! Use Tomato instead!'
,
                 
DeprecationWarning
)
vegetables.py
> python main.py
/food/vegetables.py:13: DeprecationWarning: Deprecated! Use Tomato instead!
  warnings.warn('Deprecated! Use Tomato instead!', DeprecationWarning)
from 
food.fruits 
import 
Orange
from 
food.vegetables 
import 
OldTomato
my_tomato = OldTomato()
my_orange = Orange()
Tip #4
Same logic applies to 
logging
 and methods like
basicConfig
 or 
setLevel
.
More fun
github.com/alexpilk/python-sandbox/
Slide Note
Embed
Share

In the world of Python programming, it's crucial to avoid common pitfalls and mistakes. This guide explores some misconceptions, bad practices, and pitfalls to steer clear of, offering tips on how to improve your Python coding skills. Learn from examples, understand common mistakes, and follow best practices to enhance your Python coding journey.

  • Python Programming
  • Best Practices
  • Common Mistakes
  • Coding Tips

Uploaded on Oct 04, 2024 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. Python What NOT To Do

  2. The stereotype

  3. Side effect It s way too easy to write code that works.

  4. Example: for loop basket = ['Apples', 'Oranges', 'Bananas'] basket = ['Apples', 'Oranges', 'Bananas'] for i in range(len(basket)): print(basket[i]) for item in basket: print(item)

  5. Example: for loop with index basket = ['Apples', 'Oranges', 'Bananas'] basket = ['Apples', 'Oranges', 'Bananas'] for i in range(len(basket)): print('{}. {}'.format(i, basket[i])) for i, item in enumerate(basket): print('{}. {}'.format(i, item))

  6. Learning Python the easy way Blame Python for being unreadable Write a lot of code fast Success! Understand Python is easy

  7. The solution 1. Learn how to do things in a pythonic way. 2. Learn what NOT to do.

  8. Tip #1 Google even the simplest things using this phrase:

  9. Tip #2 Read The Little Book of Python Anti-Patterns

  10. Tip #3 Stay for the rest of this talk

  11. Agenda 1. Suppressing exceptions Less obvious ways of ruining your life than except Exception 1. Enabling warnings globally How to mess up everyone's logs in an obscure fashion.

  12. Exceptions

  13. The ultimate sin try: do_something() except: do_something_else()

  14. This is almost just as bad try: do_something() except Exception: do_something_else()

  15. This forces others to sin raise Exception('Bad stuff happened!')

  16. But theres more...

  17. class FridgeError(Exception): pass class Fridge(object): def open(self): raise FridgeError('Broken Fridge') def close(self): pass def __iter__(self): pass def collect_fruits(fridge): fruits = [] try: fridge.open() for shelf in fridge: fruits += shelf.fruits finally: fridge.close() return fruits collect_fruits(Fridge())

  18. class FridgeError(Exception): pass class Fridge(object): def open(self): raise FridgeError('Broken Fridge') def close(self): pass def __iter__(self): pass def collect_fruits(fridge): fruits = [] try: fridge.open() for shelf in fridge: fruits += shelf.fruits finally: fridge.close() return fruits collect_fruits(Fridge())

  19. Traceback (most recent call last): File "main.py", line 61, in <module> collect_fruits(Fridge()) File "main.py", line 53, in collect_fruits fridge.open() File "main.py", line 41, in open raise FridgeError('Broken Fridge') __main__.FridgeError: Broken Fridge

  20. Why does this happen? A function can either return a value or raise an exception, it cannot do both.

  21. How to avoid it and live a happy life? Do not return anything in finally: block.

  22. Warnings

  23. Food package additives.py fruits.py import warnings from additives import Arsenic class ArsenicWarning(UserWarning): pass class Orange(object): class Arsenic(object): def __init__(self): self.content = Arsenic() def __init__(self): warnings.warn('This product is poisonous!', ArsenicWarning)

  24. from food.fruits import Orange my_orange = Orange() > python main.py /food/additives.py:11: ArsenicWarning: This product is poisonous! warnings.warn('This product is poisonous!', ArsenicWarning)

  25. Food package additives.py fruits.py import warnings import warnings from additives import Arsenic class ArsenicWarning(UserWarning): pass warnings.filterwarnings('ignore') class Arsenic(object): class Orange(object): def __init__(self): warnings.warn('This product is poisonous!', ArsenicWarning) def __init__(self): self.content = Arsenic()

  26. from food.fruits import Orange my_orange = Orange() > python main.py Process finished with exit code 0

  27. Food package vegetables.py class OldTomato(object): def __init__(self): pass

  28. Food package vegetables.py import warnings class Tomato(object): def __init__(self): pass def OldTomato(): warnings.warn('Deprecated! Use Tomato instead!', DeprecationWarning)

  29. from food.vegetables import OldTomato my_tomato = OldTomato() > python main.py Process finished with exit code 0

  30. Food package vegetables.py import warnings warnings.filterwarnings("always") class Tomato(object): def __init__(self): pass def OldTomato(): warnings.warn('Deprecated! Use Tomato instead!', DeprecationWarning)

  31. from food.vegetables import OldTomato my_tomato = OldTomato() > python main.py /food/vegetables.py:13: DeprecationWarning: Deprecated! Use Tomato instead! warnings.warn('Deprecated! Use Tomato instead!', DeprecationWarning)

  32. from food.vegetables import OldTomato from food.fruits import Orange my_tomato = OldTomato() my_orange = Orange() > python main.py Process finished with exit code 0

  33. from food.fruits import Orange from food.vegetables import OldTomato my_tomato = OldTomato() my_orange = Orange() > python main.py /food/vegetables.py:13: DeprecationWarning: Deprecated! Use Tomato instead! warnings.warn('Deprecated! Use Tomato instead!', DeprecationWarning) /food/additives.py:11: ArsenicWarning: This product is poisonous! warnings.warn('This product is poisonous!', ArsenicWarning)

  34. Why does this happen? warnings.filterwarnings manages warnings globally, so it s possible to affect warnings outside current module.

  35. How to avoid it and live a happy life? If possible - do not do it on library level and let the user control warnings in his own code.

  36. How to avoid it and live a happy life? If you absolutely need to - at least be precise.

  37. Food package additives.py fruits.py import warnings import warnings from additives import Arsenic, ArsenicWarning class ArsenicWarning(UserWarning): pass warnings.filterwarnings('ignore', category=ArsenicWarning, module='food.additives') class Arsenic(object): class Orange(object): def __init__(self): warnings.warn('This product is poisonous!', ArsenicWarning) def __init__(self): self.content = Arsenic()

  38. Food package vegetables.py import warnings warnings.filterwarnings('always', category=DeprecationWarning, module=__name__) class Tomato(object): def __init__(self): pass def OldTomato(): warnings.warn('Deprecated! Use Tomato instead!', DeprecationWarning)

  39. from food.fruits import Orange from food.vegetables import OldTomato my_tomato = OldTomato() my_orange = Orange() > python main.py /food/vegetables.py:13: DeprecationWarning: Deprecated! Use Tomato instead! warnings.warn('Deprecated! Use Tomato instead!', DeprecationWarning)

  40. Tip #4 Same logic applies to logging and methods like basicConfig or setLevel.

  41. More fun github.com/alexpilk/python-sandbox/

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#