Our new and simplified iterator example looks as follows: 224 6.4. If you were to use the single asterisk (*) operator to unpack the dictionary, keys would be passed to the function in random order instead: >>> print_vector(*dict_vec) Pythons function argument unpacking feature gives you a lot of flexibility for free. I mean, its fairly easy for him to come up with working solutions to most problems he faces with Python. When you install packages globally there can be only one version of a Python library across all of your programs. Thats how programming languages evolve over timeand as developers, we reap the benefits. If youd like to let me know about an error, or if you just have a question or want to offer some constructive feedback, then please email me at [emailprotected]. However, the way hash values are typically calculated isnt perfect. But, I just finished reading through every chapters in this book after 13 days of daily reading. . Beautiful Iterators >>> next(iterator) 1 >>> next(iterator) 2 >>> next(iterator) 3 Careful now! It helps to write better code, that's for granted! Because theres never more than one element in flight, this approach is highly memory-efficient. This code is equivalent to the chain of generators we built throughout the chapter: 248 6.7. Covering Your A** With Assertions Python Assertions Summary Despite these caveats I believe that Pythons assertions are a powerful debugging tool thats frequently underused by Python developers. Theyre not a mechanism for handling run-time errors. We seem to get the same results from our one-line generator expression that we got from the bounded_repeater generator function. Just like any other tool in the software development toolbox, decorators are not a cure-all and they should not be overused. In practical terms, this means local variables and the execution state of the generator function are only stashed away temporarily and not thrown out completely. The parentheses surrounding a generator expression can be dropped if the generator expression is used as the single argument to a function: 243 6.6. Python Tricks: A Buffet of Awesome Python Features. Or, to generalize: sometimes you need a way to merge two or more dictionaries into one, so that the resulting dictionary contains a combination of the keys and values of the source dicts. When I asked my colleagues for resources for learning Python, all they gave me was a link to Pythons official documentation. . In this chapter youll learn about the benefits of abstract base classes and how to define them with Pythons built-in abc module. A queue is a collection of objects that supports fast first-in, first-out (FIFO) semantics for inserts and deletes. The built-in dict type will be good enough most of the time. Calling a method in Python through the dot syntax triggers this behavior. As weve learned, static methods cant access class or instance state because they dont take a cls or self argument. . The example Im using here might look different from the examples youve seen in other iterator tutorials, but bear with me. . Just enter a Python interpreter session and run the following: >>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Because every chapter is independent from another what makes it so easy to grab and use that trick :). Behind the scenes, Python simply enforces the access restrictions by not passing in the self or the cls argument when a static method gets called using the dot syntax. itemsDesktop: [1199, 3], Whats interesting about a stack as an abstract data structure is that, at the bare minimum, it only supports two operations: push and pop. Comprehensions are a key feature in Python. . As you can see, thats quite an easy mistake to make. My goal here is to clarify how the most common abstract data types map to Pythons naming scheme and to provide a brief description for each. And if you are constantly online, your productivity takes a hit from the 296 9.2. . frozenset objects are hashable and can be used as dictionary or set keys. Two things: First, it keeps track of the index i manuallyinitializing, it to zero and then carefully incrementing it upon every loop iteration. . Today I help Python developers take their coding skills and productivity to the next level. Class vs Instance Variable Pitfalls among all instances of a class. Not one for total beginners, but if like me you find yourself at the stage of, "Well, I think I'm now OK with the basics of python, but where do I go next?" A Buffet of Awesome Python Features'. . . Then Ill apply another modification and youll see which objects are affected: >>> drect = copy.deepcopy(srect) >>> drect.topleft.x = 222 >>> drect Rectangle(Point(222, 1), Point(5, 6)) >>> rect 122 4.4. And now Mark's dream of mastering Python is slowly withering away 225 6.4. These dunder methods are often referred to as magic methodsbut many people in the Python community, including myself, dont like that word. You want to keep things simple: A plain dictionary object might be a good choice due to the convenient syntax that closely resembles JSON. Theres no buffering between the processing steps in the chain: 1. Generators Are Simplified Iterators 'Hi' 'Hi' 'Hi' Great! Either way, I promise itll be time well spent. You'll get one step closer to mastering Python, so you can write beautiful and idiomatic code that comes to you naturally. I highly recommend to read this book as early as possible. Context Managers and the with Statement This almost reads like a domain-specific language (DSL) for indenting text. This is the result we get when evaluating the above dict expression in a CPython interpreter session: >>> {True: 'yes', 1: 'no', 1.0: 'maybe'} {True: 'maybe'} Ill admit I was pretty surprised about this result the first time I saw it. Function Argument Unpacking 3.5 Function Argument Unpacking A really cool but slightly arcane feature is the ability to unpack function arguments from sequences and dictionaries with the * and ** operators. . Well now take a look at them and compare their characteristics. Instead you get a well thought out and substantial walk through many of the more advanced aspects of the language. . Lets find out: >>> for x in repeat_three_times('Hey there'): print(x) 'Hey there' 'Hey there' 'Hey there' As you may have expected, this generator stopped producing new values after three iterations. Checking for admin privileges with an assert statement is dangerous. But of course, they were two different cats, two separate beings, even though they looked exactly the same. What Namedtuples Are Good For chapter 178 5.3. Cloning Objects for Fun and Profit ject this way walks the whole object tree to create a fully independent clone of the original object and all of its children. You need to lock down field names to avoid typos: collections.namedtuple and typing.NamedTuple are your friends here. The newsletter emails I send out are not your typical heres a list of popular articles flavor. . This isnt necessarily bad, but its important to be aware of what happened here, behind the scenes. Let me try to bring some clarity to this question by giving you a somewhat real-world example: Imagine youve got 30 functions with business logic in your reportgenerating program. Dan Bader P.S. Another way to memorize the characteristics of a queue data structure is to think of it as a pipe: New items (water molecules, ping-pong balls, ) are put in at one end and travel to the other where you or someone else removes them again. However, I already knew most of them from YouTube videos. Iteration stops after the number of repetitions defined in the max_repeats parameter: >>> repeater = BoundedRepeater('Hello', 3) >>> for item in repeater: print(item) Hello Hello Hello If we rewrite this last for-in loop example to take away some of the syntactic sugar, we end up with the following expanded code snippet: repeater = BoundedRepeater('Hello', 3) iterator = iter(repeater) while True: try: 228 6.4. . Therefore, your project dependencies will be physically separated from all other Python environments on your system, including the 285 8.2. This is the name mangling that the Python interpreter applies. If youre not careful, you might have to deal with monstrous list, set, and dict comprehensions soon. . Therefore you might choose to decorate some functions manually in order to retain the ability to call the undecorated function as well. The Python interpreter automatically generates this documentation from the attributes on an object and its docstring (if available.) String Conversion (Every Class Needs a __repr__) repetition is to use the objects __class__.__name__ attribute, which will always reflect the class name as a string. Lets find out with the is operator: >>> a is c False Boom! So here it is. If the container isnt ordered, it will return its elements in arbitrary order but the loop will still cover all of them. By contributing to Python as a CPython core developer, I get connected to many members of the community. Im sure you can intuitively accept that 1.0 == 1, but why would True be considered equal to 1 as well? Now before we go on, lets take a look at what you get in the full book package: I first heard about your book from a co-worker who wanted to trick me with your example of how dictionaries are built. Pythons Functions Are First-Class You can even call a function object stored in the list without first assigning it to a variable. Decorators modify the behavior of a callable through a wrapper closure so you dont have to permanently modify the original. In this particular case, I actually prefer the lambda expression. 151 4.8. 3.5 Function Argument Unpacking . On the other hand, I feel like its time to put up another caveat: Lambda functions should be used sparingly and with extraordinary care. Sometimes calling dir() on an object will result in too much informationon a complex module or class youll get a long printout thats difficult to read quickly. . If nothing happens, download GitHub Desktop and try again. 293 Theres a difference between doing a great job as a Python developer, and to be seen doing a great job. All you get by assigning a generator expression to a variable is an iterable generator object: >>> listcomp ['Hello', 'Hello', 'Hello'] >>> genexpr To access the values produced by the generator expression, you need to call next() on it, just like you would with any other iterator: >>> next(genexpr) 'Hello' >>> next(genexpr) 'Hello' >>> next(genexpr) 'Hello' >>> next(genexpr) StopIteration Alternatively, you can also call the list() function on a generator expression to construct a list object holding all generated values: >>> genexpr = ('Hello' for i in range(3)) >>> list(genexpr) ['Hello', 'Hello', 'Hello'] 241 6.6. Even after working with python for almost 6 years now reading this book was actually very great! Now is better than never. The Zen of Python Easter Egg 2.6 The Zen of Python Easter Egg I know what follows is a common sight as far as Python books go. That seems fitting and kind of Pythonic already. The function takes a string opcode like "add" or "mul" and then does some math on the operands x and y: >>> def dispatch_if(operator, x, y): if operator == 'add': return x + y elif operator == 'sub': return x - y elif operator == 'mul': return x * y elif operator == 'div': return x / y To be honest, this is yet another toy example (I dont want to bore you with pages and pages of code here), but itll serve well to illustrate the 261 7.3. . This means you cannot add new fields or modify existing fields after the namedtuple instance was created. Imagine you had this assertion in one of your unit tests: assert ( counter == 10, 'It should have counted all the items' ) Upon first inspection, this test case looks completely fine. Records, Structs, and Data Transfer Objects >>> car1.mileage = 12 AttributeError: "can't set attribute" >>> car1.windshield = 'broken' AttributeError: "'Car' object has no attribute 'windshield'" typing.NamedTuple Improved Namedtuples This class added in Python 3.6 is the younger sibling of the namedtuple class in the collections module.21 It is very similar to namedtuple, the main difference being an updated syntax for defining new record types and added support for type hints. This time were going to create a deep copy using the deepcopy() function defined in the copy module instead: >>> import copy >>> xs = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> zs = copy.deepcopy(xs) When you inspect xs and its clone zs that we created with copy.deepcopy(), youll see that they both look identical againjust like in the previous example: >>> xs [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> zs [[1, 2, 3], [4, 5, 6], [7, 8, 9]] However, if you make a modification to one of the child objects in the original object (xs), youll see that this modification wont affect the deep copy (zs). But if the condition evaluates to false, an AssertionError exception is raised with an optional error message. Hopefully the code is trustworthy, but who knows what it will really do? Static methods dont have access to cls or self. This is a nice shorthand for clearing a list and then repopulating it manually: >>> original_lst = lst >>> lst[:] = [7, 8, 9] >>> lst [7, 8, 9] >>> original_lst [7, 8, 9] >>> original_lst is lst True The previous code example replaced all elements in lst but did not destroy and recreate the list itself. collections.Counter implements multiset or bag data structures. And explanations will be easy to understand for newcomers but at the same time it's not boring for someone who works with python for some time. Eventually I set out to create a few more Python Tricks and shared them in an email series. Lambdas Are Single-Expression Functions . . Use a list or a tuple, depending on whether you want an immutable data structure or not. Python Docs: functools.wraps 83 3.3. . Its often unclear how even well-known abstract data types like a Stack correspond to a specific implementation in Python. autoPlay: 3000, Im going to base this on the previous list-copying example. It is a good read for expanding your horizons, and one that will remain useful as a reference work when implementing some of the techniques with which you are not overly familiar. Its okay to use them. 258 7.3. However, in order for the unpacking expression to succeed, I need to assign all values contained in the tuple to variables. 4.0 out of 5 stars Good book. The author also makes a case for it not being a beginner beginner book, and I get it, the book just flows when you know a little more than the basics, but its also very helpful if youre a beginner. The raised exception tells us which method or methods were missing: 4 cf. The pprint and json module are higher-fidelity options built into the Python standard library. This module implements some of the most frequently used key funcs as plug-and-play building blocks, like operator.itemgetter and operator.attrgetter. . As someone who doesnt have my degree in CS its nice to have the text to explain things that others might have learned when they were classically educated. Sets and Multisets 5.4 Sets and Multisets In this chapter youll see how to implement mutable and immutable set and multiset (bag) data structures in Python, using built-in data types and classes from the standard library. Cloning Objects for Fun and Profit 4.4 Cloning Objects for Fun and Profit Assignment statements in Python do not create copies of objects, they only bind names to an object. 96 Chapter 4 Classes & OOP 97 4.1. Pythons assert statement is a debugging aid that tests a condition as an internal self-check in your program. In addition, hashable objects which compare as equal must have the same hash value. . Single Underscore _: Sometimes used as a name for temporary or insignificant variables (dont care). So Many Ways to Merge Dictionaries 7.5 So Many Ways to Merge Dictionaries Have you ever built a configuration system for one of your Python programs? Second, if we really wanted to do some simple arithmetic like x + y, then wed be better off using Pythons built-in operator module instead of the lambda functions used in the example. 80 3.3. Through the self parameter, instance methods can freely access attributes and other methods on the same object. Isolating Project Dependencies With Virtualenv Key Takeaways Virtual environments keep your project dependencies separated. Heres what rewriting our ManagedFile context manager example with this technique looks like: from contextlib import contextmanager @contextmanager def managed_file(name): try: f = open(name, 'w') yield f finally: f.close() >>> with managed_file('hello.txt') as f: f.write('hello, world!') . Lets first check where the global Python environment currently resides. And second, installing or updating a package with an active virtual environment means that all files will end up in a subfolder in the virtual environments directory. Both of these properties can introduce surprising bugs, and theres always a trade-off to be made between convenience and error resilience. An is expression evaluates to True if two variables point to the same (identical) object. A "must have" book for anyone who's serious about learning Python, Reviewed in the United States on May 3, 2023. A stack is a collection of objects that supports fast last-in, first-out (LIFO) semantics for inserts and deletes. Consequently I had no expectations of the book at all. collections.OrderedDict Remember the Insertion Order of Keys, collections.defaultdict Return Default Values for Missing Keys, collections.ChainMap Search Multiple Dictionaries as a Single Mapping, types.MappingProxyType A Wrapper for Making Read-Only Dictionaries. Lets see how this implementation of greeting() fares with our previous test cases: >>> greeting(382) 'Hi Alice!' Although never is often better than right now. You just saw how the slicing step size can be used to select every other element of a list. Asserts can be globally disabled with an interpreter setting. Using the **-operator is also faster than using chained update() calls, which is yet another benefit. Lets look at a simple example first so we have something to discuss. . That way we can hold onto the source object thats being iterated over. He showed me the book via video conferencing and I sort of skimmed through it as he flipped the pages for me, and I was immediately curious to read more. If youve worked with other programming languages and you want to get up to speed with Python,youll pick up the idioms and practical tips you need to become a confident and effective Pythonista. Email dbader if you ' 'encounter this in the wild. 189 5.5. . The dictionary syntax is concise and quite convenient to type. Asserts should only be used to help developers identify bugs. Heres an example: def repeat_three_times(value): yield value yield value yield value 234 6.5. To signal the end of iteration, a Python iterator simply raises the built-in StopIteration exception. For example, its possible for format strings to access arbitrary variables in your program. After much chagrin, Im personally drawing the line at one level of nesting for comprehensions. >>> s = [] >>> s.append('eat') >>> s.append('sleep') >>> s.append('code') 30 cf. Again, this happened because we had only created a shallow copy of the original list. Lets confirm that this two-class setup really made Repeater objects compatible with for-in loop iteration. Beautiful Iterators Iterating Forever Well begin by writing a class that demonstrates the bare-bones iterator protocol. How to Read This Book 1.3 How to Read This Book The best way to read Python Tricks: The Book is to treat it like a buffet of awesome Python features. . You need to store arbitrary objects, potentially with mixed data types? I hope that by now youre already feeling more comfortable using context managers and the with statement in your own Python programs. In some cases, the collections.defaultdict class from the standard library can also be helpful. Context Managers and the with Statement f = open('hello.txt', 'w') f.write('hello, world') f.close() This implementation wont guarantee the file is closed if theres an exception during the f.write() calland therefore our program might leak a file descriptor. They require a solid grasp of several advanced concepts in the language, including the properties of first-class functions. Using the range() built-in, I can generate the indexes automatically: >>> range(len(my_items)) range(0, 3) 206 6.1. Using the @ syntax is just syntactic sugar and a shortcut for this commonly used pattern. Lets try out the class method next: >>> obj.classmethod() ('class method called', ) Calling classmethod() showed us that it doesnt have access to the object, but only to the object, representing the class itself (everything in Python is an object, even classes themselves).