Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Python Unlocked
Python Unlocked

Python Unlocked: Become more fluent in Python—learn strategies and techniques for smart and high-performance Python programming

eBook
€8.99 €26.99
Paperback
€32.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Python Unlocked

Chapter 1. Objects in Depth

In this chapter, we will dive into Python objects. Objects are the building blocks of the language. They may represent or abstract a real entity. We will be more interested in factors affecting such behavior. This will help us understand and appreciate the language in a better way. We will cover the following topics:

  • Object characteristics
  • Calling objects
  • How objects are created
  • Playing with attributes

Understanding objects

Key 1: Objects are language's abstraction for data. Identity, value, and type are characteristic of them.

All data and items that we work on in a program are objects, such as numbers, strings, classes, instances, and modules. They possess some qualities that are similar to real things as all of them are uniquely identifiable just like humans are identifiable by their DNA. They have a type that defines what kind of object it is, and the properties that it supports, just like humans of type cobbler support repairing shoes, and blacksmiths support making metal items. They possess some value, such as strength, money, knowledge, and beauty do for humans.

Name is just a means to identify an object in a namespace similar to how it is used to identify a person in a group.

Identity

In Python, every object has a unique identity. We can get this identity by passing an object to built-in ID function ID (object).This returns the memory address of the object in CPython.

Interpreter can reuse some objects so that the total number of objects remains low. For example, integers and strings can be reused in the following manner:

>>> i = "asdf"
>>> j = "asdf"
>>> id(i) == id(j)
True
>>> i = 10000000000000000000000000000000
>>> j = 10000000000000000000000000000000
>>> id(j) == id(i) #cpython 3.5 reuses integers till 256
False
>>> i = 4
>>> j = 4
>>> id(i) == id(j)
True
>>> class Kls:
...     pass
... 
>>> k = Kls()
>>> j = Kls()
>>> id(k) == id(j) #always different as id gives memory address
False

This is also a reason that addition of two strings is a third new string, and, hence, it is best to use the StringIO module to work with a buffer, or use the join attribute of strings:

>>> # bad
... print('a' + ' ' + 'simple' + ' ' + 'sentence' +  ' ' + '')
a simple sentence
>>> #good
... print(' '.join(['a','simple','sentence','.']))
a simple sentence .

Value

Key 2: Immutability is the inability to change an object's value.

The value of the object is the data that is stored in it. Data in an object can be stored as numbers, strings, or references to other objects. Strings, and integers are objects themselves. Hence, for objects that are not implemented in C (or core objects), it is a reference to other objects, and we perceive value as the group value of the referenced object. Let's take an example of an object iC instance of the C class with the str and lst attributes, as shown in the following diagram:

Value

The code snippet to create this object will be as follows:

>>> class C:
...     def __init__(self, arg1, arg2):
...         self.str = arg1
...         self.lst = arg2
... 
>>> iC = C("arun",[1,2])
>>> iC.str
'arun'
>>> iC.lst
[1, 2]
>>> iC.lst.append(4)
>>> iC.lst
[1, 2, 4]

Then, when we modify iC, we are either changing the objects references via attributes, or we are changing the references themselves and not the object iC. This is important in understanding immutable objects because being immutable means not being able to change references. Hence, we can change mutable objects that are referenced by immutable objects. For example, lists inside tuple can be changed because the referenced objects are changing, not the references.

Type

Key 3: Type is instance's class.

An object's type tells us about the operations and functionality that the object supports, and it may also define the possible values for objects of that type. For example, your pet may be of type dog (an instance of the dog class) or cat (an instance of the cat class). If it is of type dog, it can bark; and if it is type cat, it can meow. Both are a type of animal (cat and dog inherit from the animal class).

An object's class provides a type to it. Interpreter gets the object's class by checking its __class__ attribute. So, we can change an object's type by changing its __class__ attribute:

>>> k = []
>>> k.__class__
<class 'list'>
>>> type(k)
<class 'list'>
# type is instance's class
>>> class M:
...     def __init__(self,d):
...         self.d = d
...     def square(self):
...         return self.d * self.d
... 
>>> 
>>> class N:
...     def __init__(self,d):
...         self.d = d
...     def cube(self):
...         return self.d * self.d * self.d
... 
>>> 
>>> m = M(4)
>>> type(m)  #type is its class
<class '__main__.M'>
>>> m.square()  #square defined in class M
16
>>> m.__class__ = N # now type should change
>>> m.cube()        # cube in class N
64
>>> type(m)
<class '__main__.N'> # yes type is changed

Note

This will not work for built-in, compiled classes as it works only for class objects defined on runtime.

Making calls to objects

Key 4: All objects can be made callable.

To reuse and group code for some task, we group it in the functions classes, and then call it with different inputs. The objects that have a __call__ attribute are callable and __call__ is the entry point. For the C class, tp_call is checked in its structure:

>>> def func(): # a function
...     print("adf")
... 
>>> func()
adf
>>> func.__call__() #implicit call method
adf
>>> func.__class__.__call__(func)
adf
>>> func.__call__
<method-wrapper '__call__' of function object at 0x7ff7d9f24ea0>
>>> class C: #a callable class
...     def __call__(self):
...         print("adf")
... 
>>> c = C()
>>> c()
adf
>>> c.__call__() #implicit passing of self
adf
>>> c.__class__.__call__(c) #explicit passing of self
adf
>>> callable(lambda x:x+1)  #testing whether object is callable or not
True
>>> isinstance(lambda x:x+1, collections.Callable) #testing whether object is callable or not
True

Methods in classes are similar to functions, except that they are called with an implicit instance as a first argument. The functions are exposed as methods when they are accessed from the instance. The function is wrapped in a method class and returned. The method class stores instances in __self__ and function in __func__, and its __call__ method calls __func__ with first argument as __self__:

>>> class D:
...     pass
... 
>>> class C:
...     def do(self,):
...             print("do run",self)
... 
>>> def doo(obj):
...     print("doo run",obj)
... 
>>> c = C()
>>> d = D()
>>> doo(c)
doo run <__main__.C object at 0x7fcf543625c0>
>>> doo(d)
doo run <__main__.D object at 0x7fcf54362400>
>>> # we do not need to pass object in case of C class do method
... 
>>> c.do() #implicit pass of c object to do method
do run <__main__.C object at 0x7fcf543625c0>
>>> C.doo = doo
>>> c.doo()
doo run <__main__.C object at 0x7fcf543625c0>
>>> C.doo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: doo() missing 1 required positional argument: 'obj'
>>> C.do()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: do() missing 1 required positional argument: 'self'
>>> C.do(c)
do run <__main__.C object at 0x7fcf543625c0>
>>> C.do(d)
do run <__main__.D object at 0x7fcf54362400>
>>> c.do.__func__(d) #we called real function this way
do run <__main__.D object at 0x7fcf54362400>

Using this logic, we can also collect methods that are needed from other classes in the current class, like the following code, instead of multiple inheritances if data attributes do not clash. This will result in two dictionary lookups for an attribute search: one for instance, and one for class.

>>> #in library
... class PrintVals:
...     def __init__(self, endl):
...         self.endl = endl
...         
...     def print_D8(self, data):
...         print("{0} {1} {2}".format(data[0],data[1],self.endl))
... 
>>> class PrintKVals: #from in2 library
...     def __init__(self, knm):
...         self.knm = knm
...     
...     def print_D8(self, data):
...         print("{2}:{0} {1}".format(data[0],data[1],self.knm))
...
>>> class CollectPrint:
...     
...     def __init__(self, endl):
...         self.endl = endl
...         self.knm = "[k]"
...     
...     print_D8 = PrintVals.print_D8
...     print_D8K = PrintKVals.print_D8
... 
>>> c = CollectPrint("}")
>>> c.print_D8([1,2])
1 2 }
>>> c.print_D8K([1,2])
[k]:1 2

When we call classes, we are calling its type, that is metaclass, with class as a first argument to give us a new instance:

>>> class Meta(type):
...     def __call__(*args):
...         print("meta call",args)
... 
>>> class C(metaclass=Meta):
...     pass
... 
>>> 
>>> c = C()
meta call (<class '__main__.C'>,)
>>> c = C.__class__.__call__(C)
meta call (<class '__main__.C'>,)

Similarly, when we call instances, we are calling their type, that is class, with instance as first argument:

>>> class C:
...     def __call__(*args):
...         print("C call",args)
... 
>>> c = C()
>>> c()
C call (<__main__.C object at 0x7f5d70c2bb38>,)
>>> c.__class__.__call__(c)
C call (<__main__.C object at 0x7f5d70c2bb38>,)

How objects are created

Objects other than built-in types or compiled module classes are created at runtime. Objects can be classes, instances, functions, and so on. We call an object's type to give us a new instance; or put in another way, we call a type class to give us an instance of that type.

Creation of function objects

Key 5: Create function on runtime.

Let's first take a look at how function objects can be created. This will broaden our view. This process is done by interpreter behind the scenes when it sees a def keyword. It compiles the code, which is shown as follows, and passes the code name arguments to the function class that returns an object:

>>> function_class = (lambda x:x).__class__
>>> function_class
<class 'function'>
>>> def foo():
...     print("hello world")
... 
>>> 
>>> def myprint(*args,**kwargs):
...     print("this is my print")
...     print(*args,**kwargs)
... 
>>> newfunc1 = function_class(foo.__code__, {'print':myprint})
>>> newfunc1()
this is my print
hello world
>>> newfunc2 = function_class(compile("print('asdf')","filename","single"),{'print':print})
>>> newfunc2()
asdf

Creation of instances

Key 6: Process flow for instance creation.

We call class to get a new instance. We saw from the making calls to objects section that when we call class, it calls its metaclass __call__ method to get a new instance. It is the responsibility of __call__ to return a new object that is properly initialized. It is able to call class's __new__, and __init__ because class is passed as first argument, and instance is created by this function itself:

>>> class Meta(type):
...     def __call__(*args):
...         print("meta call ",args)
...         return None
... 
>>> 
>>> class C(metaclass=Meta):
...     def __init__(*args):
...         print("C init not called",args)
... 
>>> c = C() #init will not get called 
meta call  (<class '__main__.C'>,)
>>> print(c)
None
>>>

To enable developer access to both functionalities, creating new object, and initializing new object, in class itself; __call__ calls the __new__ class to return a new object and __init__ to initialize it. The full flow can be visualized as shown in the following code:

>>> class Meta(type):
...     def __call__(*args):
...         print("meta call ,class object :",args)
...         class_object = args[0]
...         if '__new__' in class_object.__dict__:
...             new_method = getattr(class_object,'__new__',None)
...             instance = new_method(class_object)
...         else:
...             instance = object.__new__(class_object)
...         if '__init__' in class_object.__dict__:
...             init_method =  getattr(class_object,'__init__',None)
...             init_method(instance,*args[1:])
...         return instance
...
>>> class C(metaclass=Meta):
...     def __init__(instance_object, *args):
...         print("class init",args)
...     def __new__(*args):
...         print("class new",args)
...         return object.__new__(*args)
...
>>> class D(metaclass=Meta):
...     pass
...
>>> c=C(1,2)
meta call ,class object : (<class '__main__.C'>, 1, 2)
class new (<class '__main__.C'>,)
class init (1, 2)
>>> d = D(1,2)
meta call ,class object : (<class '__main__.D'>, 1, 2)
>>>

Take a look at the following diagram:

Creation of instances

Creation of class objects

Key 7: Process flow for class creation.

There are three ways in which we can create classes. One is to simply define the class. The second one is to use the built-in __build_class__ function, and the third is to use the new_class method of type module. Method one uses two, method two uses method three internally. When interpreter sees a class keyword, it collects the name, bases, and metaclass that is defined for the class. It will call the __build_class__ built-in function with function (with the code object of the class), name of the class, base classes, metaclass that is defined, and so on:

__build_class__(func, name, *bases, metaclass=None, **kwds) -> class

This function returns the class. This will call the __prepare__ class method of metaclass to get a mapping data structure to use as a namespace. The class body will be evaluated, and local variables will be stored in this mapping data structure. Metaclass's type will be called with this namespace dictionary, bases, and class name. It will in turn call the __new__ and __init__ methods of metaclass. Metaclass can change attributes passed to its method:

>>> function_class = (lambda x:x).__class__
>>> M = __build_class__(function_class(
...                         compile("def __init__(self,):\n    print('adf')",
...                                 '<stdin>',
...                                 'exec'),
...                         {'print':print}
...                         ),
...                     'MyCls')
>>> m = M()
adf
>>> print(M,m)
<class '__main__.MyCls'> <__main__.MyCls object at 0x0088B430>
>>>

Take a look at the following diagram:

Creation of class objects

Playing with attributes

Key 8: Which attribute will be used.

Attributes are values that are associated with an object that can be referenced by name using dotted expressions. It is important to understand how attributes of an object are found. The following is the sequence that is used to search an attribute:

  1. If an attribute is a special method, and it exists in the object's type (or bases), return it, for example: __call__, __str__, and __init__. When these methods are searched, their behavior is only in the instance's type:
    >>> class C:
    ...     def __str__(self,):
    ...             return 'Class String'
    ...     def do(self):
    ...             return 'Class method'
    ... 
    >>> c = C()
    >>> print(c)
    Class String
    >>> print(c.do())
    Class method
    >>> def strf(*args):
    ...     return 'Instance String',args
    ... 
    >>> def doo(*args):
    ...     return 'Instance Method'
    ... 
    >>> c.do = doo
    >>> c.__str__ = strf
    >>> print(c)
    Class String
    >>> print(c.do())
    Instance Method
  2. If an object's type has a __getattribute__ attribute, then this method is invoked to get the attribute whether this attribute is present or not. It is the total responsibility of __getattribute__ to get the attribute. As shown in the following code snippet, even if the do method is present, it is not found as getattribute didn't return any attribute:
    >>> class C:
    ...     def do(self):
    ...             print("asdf")
    ...     def __getattribute__(self,attr):
    ...             raise AttributeError('object has no attribute "%s"'%attr)
    ... 
    >>> c = C()
    >>> c.do()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 5, in __getattribute__
    AttributeError: object has no attribute "do"
    >>> 
  3. Search in object's type __dict__ to find the attribute. If it is present, and it is data descriptor, return it:
    >>> class Desc:
    ...     def __init__(self, i):
    ...             self.i = i
    ...     def __get__(self, obj, objtype):
    ...             return self.i
    ...     def __set__(self,obj, value):
    ...             self.i = value
    ...
    >>> class C:
    ...     attx = Desc(23)
    ...
    >>> c = C()
    >>> c.attx
    23
    >>> c.__dict__['attx'] = 1234
    >>> c.attx
    23
    >>> C.attx = 12
    >>> c.attx
    1234
  4. Search in object's __dict__ type (and if this object is class, search bases __dict__ as well) to find the attribute. If the attribute is descriptor, return the result.
  5. Search in object's type__dict__ to find the attribute. If the attribute is found, return it. If it is non-data descriptor, return its result, and check in other bases using the same logic:
    >>> class Desc:
    ...     def __init__(self, i):
    ...             self.i = i
    ...     def __get__(self, obj, objtype):
    ...             return self.i
    ...
    >>> class C:
    ...     attx = Desc(23)
    ...
    >>> c = C()
    >>> c.attx
    23
    >>> c.__dict__['attx'] = 34
    >>> c.attx
    34
  6. If object type's __getattr__ is defined, check whether it can give us the attribute:
    >>> class C:
    ...     def __getattr__(self, key):
    ...             return key+'_#'
    ...
    >>> c = C()
    >>> c.asdf
    'asdf_#'
  7. Raise AttributeError.

Descriptors

Key 9: Making custom behavior attributes.

Any attribute of a class, which is an object defining any of these methods, acts as a descriptor:

  • __get__(self, obj, type=None) --> value
  • __set__(self, obj, value) --> None
  • __delete__(self, obj) --> None

When an attribute is searched in an object first, it is searched in its dictionary then its type's (base class's) dictionary. If found, object has one of these methods defined and that method is invoked instead. Let's assume that b is an instance of the B class, then the following will happen:

  • Invocation through class is type.__getattribute__() transforming to B.__dict__['x'].__get__(None, B)
  • Invocation through instance is object .__getattribute__() --> type(b).__dict__['x'].__get__(b, type(b))

Objects with only __get__ are non-data descriptors, and objects that include __set__ / __del__ are data descriptors. Data descriptors take precedence over instance attributes, whereas non-data descriptors do not.

Class, static, and instance methods

Key 10: Implementing class method and static method.

Class, static, and instance methods are all implementable using descriptors. We can understand descriptors and these methods in one go:

  • Class methods are methods that always get class as their first argument and they can be executed without any instance of class.
  • Static methods are methods that do not get any implicit objects as first argument when executed via class or instance.
  • Instance methods get instances when called via instance but no implicit argument when called via class.

A sample code usage of these methods is as follows:

>>> class C:
...     @staticmethod
...     def sdo(*args):
...             print(args)
...     @classmethod
...     def cdo(*args):
...             print(args)
...     def do(*args):
...             print(args)
...
>>> ic = C()
# staticmethod called through class: no implicit argument is passed
>>> C.sdo(1,2)
(1, 2)
# staticmethod called through instance:no implicit argument is passed
>>> ic.sdo(1,2)(1, 2)
# classmethod called through instance: first argument implicitly class
>>> ic.cdo(1,2)
(<class '__main__.C'>, 1, 2)
# classmethod called through class: first argument implicitly class
>>> C.cdo(1,2)
(<class '__main__.C'>, 1, 2)
# instancemethod called through instance: first argument implicitly instance
>>> ic.do(1,2)
(<__main__.C object at 0x00DC9E30>, 1, 2)
#instancemethod called through class: no implicit argument, acts like static method.
>>> C.do(1,2)
(1, 2)

They can be understood and implemented using descriptors easily as follows:

from functools import partial
>>> class my_instancemethod:
...     def __init__(self, f):
...         # we store reference to function in instance
...         # for future reference
...         self.f = f
...     def __get__(self, obj, objtype):
...         # obj is None when called from class
...         # objtype is always present
...         if obj is not None:
...             return partial(self.f,obj)
...         else: # called from class
...             return self.f
...
>>> class my_classmethod:
...     def __init__(self, f):
...         self.f = f
...     def __get__(self, obj, objtype):
...         # we pass objtype i.e class object
...         # when called from instance or class
...         return partial(self.f,objtype)
...
>>> class my_staticmethod:
...     def __init__(self, f):
...         self.f = f
...     def __get__(self, obj, objtype):
...         # we do not pass anything
...         # for both conditions
...         return self.f
...
>>> class C:
...     @my_instancemethod
...     def ido(*args):
...         print("imethod",args)
...     @my_classmethod
...     def cdo(*args):
...         print("cmethod",args)
...     @my_staticmethod
...     def sdo(*args):
...         print("smethod",args)
...
>>> c = C()
>>> c.ido(1,2)
imethod (<__main__.C object at 0x00D7CBD0>, 1, 2)
>>> C.ido(1,2)
imethod (1, 2)
>>> c.cdo(1,2)
cmethod (<class '__main__.C'>, 1, 2)
>>> C.cdo(1,2)
cmethod (<class '__main__.C'>, 1, 2)
>>> c.sdo(1,2)
smethod (1, 2)
>>> C.sdo(1,2)
smethod (1, 2)

Tip

Downloading the example code

You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Summary

In this chapter, we dived into how objects work in the Python language, how are they connected, and how are they called. Descriptors and instance creation are very important topics as they give us a picture of how system works. We also dived into how attributes are looked up for objects.

Now, we are all prepared to learn how to use language constructs to their maximum potential. In the next chapter, we will also discover utilities that are extremely helpful in elegantly finishing a project.

Left arrow icon Right arrow icon

Key benefits

  • Write smarter, bug-free, high performance code with minimal effort
  • Uncover the best tools and options available to Python developers today
  • Deploy decorators, design patters, and various optimization techniques to use Python 3.5 effectively

Description

Python is a versatile programming language that can be used for a wide range of technical tasks—computation, statistics, data analysis, game development, and more. Though Python is easy to learn, it’s range of features means there are many aspects of it that even experienced Python developers don’t know about. Even if you’re confident with the basics, its logic and syntax, by digging deeper you can work much more effectively with Python – and get more from the language. Python Unlocked walks you through the most effective techniques and best practices for high performance Python programming - showing you how to make the most of the Python language. You’ll get to know objects and functions inside and out, and will learn how to use them to your advantage in your programming projects. You will also find out how to work with a range of design patterns including abstract factory, singleton, strategy pattern, all of which will help make programming with Python much more efficient. Finally, as the process of writing a program is never complete without testing it, you will learn to test threaded applications and run parallel tests. If you want the edge when it comes to Python, use this book to unlock the secrets of smarter Python programming.

Who is this book for?

If you are a Python developer and you think that you don’t know everything about the language yet, then this is the book for you. We will unlock the mysteries and re-introduce you to the hidden features of Python to write efficient programs, making optimal use of the language.

What you will learn

  • Manipulate object creation processes for instances, classes, and functions
  • Use the best possible language constructs to write data structures with super speed and maintainability
  • Make efficient use of design patterns to decrease development time and make your code more maintainable
  • Write better test cases with an improved understanding of the testing framework of Python and unittests, and discover how to develop new functionalities in it
  • Write fully-optimized code with the Python language by profiling, compiling C modules, and more
  • Unlock asynchronous programming to build efficient and scalable applications
Estimated delivery fee Deliver to Portugal

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Dec 30, 2015
Length: 172 pages
Edition : 1st
Language : English
ISBN-13 : 9781785885990
Category :
Languages :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Portugal

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Publication date : Dec 30, 2015
Length: 172 pages
Edition : 1st
Language : English
ISBN-13 : 9781785885990
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 102.97
Python Unlocked
€32.99
Python GUI Programming Cookbook
€36.99
Mastering Python
€32.99
Total 102.97 Stars icon
Banner background image

Table of Contents

9 Chapters
1. Objects in Depth Chevron down icon Chevron up icon
2. Namespaces and Classes Chevron down icon Chevron up icon
3. Functions and Utilities Chevron down icon Chevron up icon
4. Data Structures and Algorithms Chevron down icon Chevron up icon
5. Elegance with Design Patterns Chevron down icon Chevron up icon
6. Test-Driven Development Chevron down icon Chevron up icon
7. Optimization Techniques Chevron down icon Chevron up icon
8. Scaling Python Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
(2 Ratings)
5 star 50%
4 star 0%
3 star 0%
2 star 0%
1 star 50%
Eduardo j. Morales Jan 16, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
The inners of the interpreter are explained clearly and mind opening to more. Concise and specific.
Amazon Verified review Amazon
Jascha Casadio Jul 23, 2016
Full star icon Empty star icon Empty star icon Empty star icon Empty star icon 1
And yet another Python book. Being such a clean and flexible has brought this 20 years old programming language to be one of the hottest ones out there. Like it or not, most of the active repositories on GitHub are on Python. This is also confirmed by multiple sources listing the most demanded programming languages in the IT world. We Pythonists are lucky because, apart from a nice documentation, there is plenty of books to pick from, even though most of them cover basic features of the language. Python Unlocked does not belong to this large group of titles and focuses itself on intermediate topics.Released at the end of 2015, Python Unlocked is a short book targeting that niche of Pythonists interested in intermediate to advanced topics, such as decorators, abstract classes and unit testing.Let's dive into the content!The very first things that comes to the eye of the reader is poor English writing skills. True, Packt Publishing does not offer authors any kind of proofreading service but someone should at least check if articles are present. The reader, sometimes after a second pass through the sentence, can still grasp what the author wanted to say, but this definitely lowers the overall quality of the title.English apart, the choice of topics somehow got me raising an eyebrow in doubt: abstract classes are definitely a subject an intermediate Python developer wants to know of, but the MRO is probably misplaced here. Unless you are going to work in the core of the language itself, and are smart enough to prefer mixins to multiple inheritance, you can definitely live without knowing about it.Unnecessary complexities are present everywhere. So are unclear explanations. For example, the book starts discussing the internals of an object. The author states When an attribute is searched in an object first, it is searched in its dictionary then its type's (base class's) dictionary. Fine, but what is that __dict__ that I see everywhere? Either you introduce me to it, and explain me what it is or, if I am supposed to know what it represents already then the whole chapter is superfluous.Let's continue. Decorators are callable objects, which replace the original callable objects with some other objects. This is not correct. A decorator can replace the original callable with another one, but it must not. No words about decorators with a variable number of arguments, which is a very interesting aspect of decorators. Only later on, paged ahead, the author dedicates a couple of lines explaining functools.wrap.The examples are usually very short, Hello world! like pieces of code, whose functions are given names like f1, f2 and foo and whose body does little more than print('adf').Overall, a poor effort. The concepts are not properly explained and the examples are too short and focused on unnecessary complexities. Anyone interested in intermediate to advanced Python topics should pick any of the following titles, instead:Fluent PythonEffective Python: 59 Specific Ways to Write Better PythonAs usual, you can find more reviews on my personal blog: books.lostinmalloc.com. Feel free to pass by and share your thoughts!
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela