Python basics
Python Basics#
- Python Basics
- Introduction
- Data Types
- Variables
- Operators
- Generators
- Statements
- Expressions
- Operators
- Functions
- Exception Handling
- Performance
- Misc
- Copy
Introduction#
The Zen of Python (PEP 20)#
- Beautiful is better than ugly.
- Explicit is better than implicit.
- Simple is better than complex.
- Complex is better than complicated.
- Flat is better than nested.
- Sparse is better than dense.
- Readability counts.
- Special cases aren't special enough to break the rules.
- Although practicality beats purity.
- Errors should never pass silently.
- Unless explicitly silenced.
- In the face of ambiguity, refuse the temptation to guess.
- There should be one-- and preferably only one --obvious way to do it.
- Although that way may not be obvious at first unless you're Dutch.
- Now is better than never.
- Although never is often better than right now.
- If the implementation is hard to explain, it's a bad idea.
- If the implementation is easy to explain, it may be a good idea.
- Namespaces are one honking great idea -- let's do more of those!
Easter Egg#
- In computer software and media, an Easter egg is an intentional inside joke, hidden message or image, or secret feature of a work
The Zen of python can be listed by importing this
1 |
|
Implementations#
- CPython (Default)
- Jython
- IronPython
- RPython (PyPy)
Internal#
- Runs on a single process by forking
- Each process have seperate GIL
- Python can run only one thread at once
- Context Manager
PEP 8 - Style Guide for Python Code#
- Package: lowercase, '_' is discouraged, use hyphen '-' instead
- Module: lowercase + '_'
- Class: Initial Capital, Camal Case
- Function: lowercase, Valid word, '_'
- Method: self, lowercase, Valid word, '_'
- Variable: Same as functions
- Local:
- Global:
- Static:
- Constant: Generally Module Level, All CAPS + '_'
- Private Attribute: To avoid name clashes with subclasses, Leading dunder
- Protected Attribute: For non-public methods and instance variables, Leading underscore '_'
- Exception Name: Same as class
NOTE: Never use the characters 'l' (lowercase letter el), 'O' (uppercase letter oh), or 'I' (uppercase letter eye) as single character variable names.
Features of Python are:#
- Unique
- Interpreted Language
- Dynamic type system but strongly typed (changing data type need explicit conversion)
- emphasizes on code readability - lesser line of code/syntax
- Supports multiple programming paradigms, including object-oriented, imperative, functional and procedural
- Has community based developement model
- Dynamic name resolution/ late binding: unlike compiled languages, the name of method, variable is lookedup by name at runtime
- Data types are strongly and dynamically typed. Mixing incompatible types (e.g. attempting to add a string and a number) causes an exception to be raised, so errors are caught sooner.
- Python contains advanced programming features such as generators and list comprehensions.
- Lambda functions
- Multiple inheritance
- Common
- A variety of basic data types are available: numbers (floating point, complex, and unlimited-length long integers), strings (both ASCII and Unicode), lists, and dictionaries.
- Python supports object-oriented programming with classes and multiple inheritance.
- Code can be grouped into modules and packages.
- The language supports raising and catching exceptions, resulting in cleaner error handling.
- Python's automatic memory management frees you from having to manually allocate and free memory in your code.
Compilers#
A type of translator.
Compiler analyze the whole source code at once and translate it to another language. i.e. machine code
Interpreters#
An interpreter is also a program that translates a high-level language into a low-level one (but not directly into machine code), and it does it at the moment the program is run.
It takes the program, one line at a time, and translates each line before running it: It translates the first line and runs it, then translates the second line and runs it etc.
Compiler characteristics:#
- spends a lot of time analyzing and processing the program
- the resulting executable is some form of machine- specific binary code
- the computer hardware interprets (executes) the resulting code
- program execution is fast
Interpreter characteristics:#
- relatively little time is spent analyzing and processing the program
- the resulting code is some sort of intermediate code
- the resulting code is interpreted by another program
- program execution is relatively slow
Python interpreted/compiled?#
Compiled Language#
A compiled language turn human-readable code into machine code (a string of binary numbers), which are directly executed by OS & CPU.
Interpreted Language#
A language which is in non-machine code form just before its execution.
In general an interpreted prog. language turn human-readable code into non-machine code (byte-code), which are then line by line executed by virtual machine.
Interpreted/Compiled is not property of language, its property of implementation.
Its byte-code INTERPRETED, because .py is first COMPILED/translated to .pyc (a byte-code language, a non-machine language, executed by python virtual machine, not by OS / CPU).
How python works?#
- run module i.e. .py file
- .py loaded into memory
- parsing in order
- .py compiled to bytecode .pyc file (which is not binary machinecode)
- compilation is translation step
- .pyc (.i.e. bytecode) is low-level platform -independent version of source-code
- require more work than CPU instructions
- if .pyc of source code is present, compilation step will be skipped by checking time-stamp of .py & .pyc
- if python cannot create .pyc, then bytecode will be created in-memory
- then routed/shipped to python virtual machine PVM for execution
- pre-installed / inbuilt
- it is runtime engine of python
- .pyc is also way of shipping python code without source-code
Note#
- no initial/explicit compilation phase
- compiles at runtime only and then executes in single step
- able to produce executable, frozen binaries using
- py2exe
- PyInstaller
- freeze
What is .pyc file?#
Low-level Platform-independent Bytecode
What is .pyo file?#
in addition to .pyc, .pyo removes all the comments & docs(i guess)
Memory Management#
-
Basics:
- Python's memory allocation and deallocation method is automatic.
- involves a private heap
- the heap contains all the objects & data structures
- managed by python "memory manager MM"
- interpreter manages this all
- no user control
- heap space allocation for objects & buffers are performed on-demand by MM
- c memory management libs works in-behind: malloc(), calloc(), realloc(), free()
- at low level, raw memory allocator allocates enough memory for all the data
- on top of low-level, object-specific allocators allocates memory as per object's policies
- e.g. for integer: speed tradeoff
-
Memory De-allocation Strategies:
-
Reference Counting
- Was only option Prior Python 2.0
- When an object gets created and referenced, it counts the number of times the object is referenced by some other objects
- When reference is removed, the reference count for the object is decremented
- When the reference count becomes zero, the object is deallocated.
- Extremely efficient but
- Have limitations like:
- Cannot handle reference cycle
- Reference Cycle: When there is no way to reach an object but its reference count is still greater than zero
- e.g.
1 2
list1 = [] list1.append(list1)
- Examples, where the reference count increases:
- assignment operator
- argument passing
- appending an object to a list (object's reference count will be increased).
1 2 3 4 5 6 7 8 9 10 11 12 13
foo = [] # 2 references, 1 from the foo var and 1 from getrefcount print(sys.getrefcount(foo)) def bar(a): # 4 references # from the foo var, function argument, getrefcount and Python's function stack print(sys.getrefcount(a)) bar(foo) # 2 references, the function scope is destroyed print(sys.getrefcount(foo))
-
Garbage Collection
- Introduced after Python 2.0
- it contains reference counting as well as garbage collector
- Automatic / Scheduled: The "Reference Counting" mechanism was not able to deallocate objects in few cases like: Reference Cycle
-
How reference counting is solved by garbage collection
-
it is a scheduled task based on a threshold
- threshold = allocations - de-allocations
-
The GC classifies container objects into three generations. Every new object starts in the first generation. If an object survives a garbage collection round, it moves to the older (higher) generation. Lower generations are collected more often than higher. Because most of the newly created objects die young, it improves GC performance and reduces the GC pause time.
- Source :
- read Pro Python for better understanding
- https://rushter.com/blog/python-garbage-collector/
- whenever threshold is reached, garbage collector starts identifying memory spaces which are garbage
- garbage?
-
the memory spaces which are un-reachable to python objects
- e.g.
- it is most important to identify a memory space whether it is a garbage or not - otherwise it will lead to1 2 3 4 5 6 7 8
import gc gc.disable() obj1 = {"val":1} obj2 = {"val":2} obj1["obj2"] = obj2 obj2["obj1"] = obj1 del obj1, obj2
memory leak
-memory leak
means, automatically data loss
-
- garbage?
-
-
Note: Automatic garbage collection will not run if your Python device is running out of memory
- Manual / Explicitly
1 2 3 4 5 6
import gc # get_count() returns a tuple of (threshold, no. of objects allocated, no. of objects de-allocated) print(gc.get_count()) # With no arguments, run a full collection gc.collect()
-
-
https://docs.python.org/3/c-api/memory.html
- pass by value
- pass by reference
- change reference
- change value
- behaviour of mutable and immutable
Data types in python?#
data type: set of data with predefined values.
- primitive:
- integers
- floating
- char
- string
- user-defined
Data structure in python?#
Data Structure: are special format/structures to store & organize data.
4 Built in#
- Sequence data types:
- Ordered Sequence:
- List
- Tuple
- Set
- Ordered Sequence:
- Dictionary
We consider string more as a data type.
Collection & heapq modules#
- provides additional data structure
- collections:
- dequeue
- ordereddict
- heapq:
- priority queue
- heap
Abstract data type we can create are#
- linear:
- linked list
- stack
- queue
- hash table
- non-linear:
- tree
- graph
Data Types#
Strings#
String formatting#
1 2 3 4 5 6 7 8 9 10 11 12 |
|
What is doc string?#
- way of associating document with modules, functions, class, methods
- describes what it does instead how
- first line should heading (start with capital, end with dot), then gap of one-line, then desc
byte string vs unicode string#
Intro#
- there are a lot of encodings available world-wide
- e.g. ASCII, CP-1252 (windows), Mac-greek.. etc
- computer only understands bit, bytes
- e.g. in ASCII: 65 is -a, 97 is A
- HOW TO REPRESENT ALL LANGUAGEs IN SAME FILE?
3 things#
str
python object- byte string, computer native array of bytes
- unicode, some encoded text
unicode#
- one encoding, all chars
- represent a char as 4-byte number: 4*8 = 32; UTF-32
- a lot memory freak
- similarly, 2*8 = 16; UTF-16
- UTF-8
- a variable-length encoding system for Unicode
- till 128, ASCII & UTF-8 is same, uses 1 byte
- uses 2 bytes for latin
List#
Intro#
- A data structure/type to store objects/data/items
- Ordered collection: stores in ordered way i.e. using index from 0
- Variable length: dynamic sized
- Mutable: can change any existing element in run-time
- Preferred for homogenious collection, but can store heterogenious data types inside.
- many attribute/member methods:
Why? When?#
- when dynamic data structure is benificial like: appending, removing, altering
- use when implementing buffer, stack, queues
Features#
List Generator#
- generates iterable items on demand
- build up in memory
- xrange in Python 2.x i.e. range() in Python 3.x is example of generator
- Advantages:
- No need to wait until all the elements have been generated before we use them
- in python 2.x, range returns a list while xrange returns a generator
- e.g.
1 2 3 4 5 6 7 8 |
|
List comprehension#
1 2 |
|
1 |
|
List Flattening#
1 2 |
|
which is equivalent to
1 2 3 4 5 |
|
Randomize items of list in place#
Code:
1 2 3 4 5 6 |
|
1 2 |
|
How to insert an element in between a list?#
Code:
1 2 3 |
|
1 |
|
Diif between append and extend method in list?#
- append - appends object at the end
- extend - extends list by appending elements from iterables
Code:
1 2 3 4 5 6 7 8 |
|
1 |
|
enumerate()#
1 2 3 4 |
|
Tuple#
- A fixed data structure/type to store objects/data/items
- Ordered collection: stores in ordered way i.e. using index from 0
- Fixed length: cannot change length of a tuple, cannot append, pop an element
- Immutable: cannot change any existing element in run-time
- Preferred for heterogenious collection, but can store homoge data types inside.
Why? When?#
- when a collection of values will not change i.e. in case of functions args.
- use when fixed structure is benificial like: heavy memory intensive work, api, server
- can be used as key in dictionary due to its fixed structure
- use when need to store a db table data and want to maintain column structure
Properties#
1 2 3 4 5 6 7 8 9 10 |
|
Expanding Tuple#
- used to pass tuple elements as function parameter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Dictionary#
- Is map type of data structure which holds a key value pair.
- Unordered collection: does not maintain order
When to use dict & set?#
- When data is labelled
- Use a dictionary when you have a set of unique keys that map to values.
- Use a set to store an unordered unique set of items.
dict vs list lookup performance?#
- dict - O(1) due to hashing
- list - O(n)
dict comprehension#
Code:
1 2 3 |
|
Out:
1 |
|
dict with order#
- maintains the order of elements in which they were inserted
1 2 3 |
|
{}
vs dict()
#
tl;dr
- use
{}
overdict()
whenever possible {}
uses transient memory allocation, and frees the memory after value being consumed- if
{}
value is assigned to a variable, then memory is persist
- if
dict()
is slower (takes atleast double the time)
Ref: - https://stackoverflow.com/questions/664118/whats-the-difference-between-dict-and - https://doughellmann.com/posts/the-performance-impact-of-using-dict-instead-of-in-cpython-2-7-2/
Variables#
Global vs Local vs Non-Local Variable#
- src: https://www.python-course.eu/python3_global_vs_local_variables.php
- not same as other languages (by default global)
- by default all are local (if you need, declare global)
1 2 3 4 5 6 7 |
|
1 2 |
|
Global Variable#
How to access global variable inside a function:
1 2 3 4 5 6 7 8 9 |
|
1 2 |
|
Global Variables in Nested Functions#
- keyword global inside inner function will not access the upper function level variable
- instead, it will create a variable in __main __ scope
- to make it possible there is one more keyword : nonlocal
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 |
|
Local Variable#
- variable defined inside a function are local to that function
Non-Local Variable#
- introduced in Python 3
- different than global
- can only be used inside of nested functions
- has to be defined in the enclosing/upper function scope
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Out:
1 2 3 4 |
|
Operators#
in
#
- Searching
- Time Complexity: (Depends on type of operand)
- List
- Avg: O(n)
- Dict/Set
- Avg: O(1)
- Worst: O(n)
- List
- magic/member method:
__contains__(<element>)
and
#
or
#
xor
#
is
#
not
#
Generators#
xrange vs range?#
** python3: ** * xrange is renamed to range.
** python2:** * same result but xrange is more memory efficient * range creates iterable list (in python2) * while xrange creates xrange object and generate list of demand
Statements#
assert#
- A statement
- Used to check an expectation
- Works on logical condition
- If true, return nothing, if false raise AssertionError exception
yield#
- A statement
- Does not end a function
- Returns value to its caller
- suspends the function and then return value to its caller then resume the function
- Continues with next line of statement
- uses: in
generators
likerange
return#
- A statement
- Ends function
- Returns value to caller
Compound Statements#
- Compound statements contain (groups of) other statements
- they affect or control the execution of those other statements in some way
- contains multi line code block
- e.g.
if
,while
,for
,def
,class
,with
with#
- The
with
statement is used to wrap the execution of a block with methods defined by a context manager with
statement allows the execution of initialization and finalization code around a block of code- i.e.
try
/finally
+context manager
having methods__enter__()
&__exit__()
- read more
Example #1 : file handling#
1 2 3 4 5 6 7 |
|
with
statement opens a file or acquires a resource then do some block of codes- then closes the file or releases the resource
- if any exception occur, during operations closes the file before exception is caught and shown by interpreter
- thats how we are better than
try, except, finally
- I/O operation : GIL free
Example #2:#
1 2 |
|
1 2 3 |
|
Expressions#
lambda#
Operators#
Ternary Operator#
[on-true] if [expression] else [on-flase]
Code:
1 2 3 |
|
1 |
|
[Operator Overloading Using Magic Methods]#
- Read in Python-OOPs notebook
Functions#
- Source
- https://docs.python.org/3/library/functions.html
eval()
#
- Source:
- https://www.programiz.com/python-programming/methods/built-in/eval
- a built-in function to evaluate the python expression writter in string form
1 2 3 4 5 6 7 8 9 |
|
partial()
#
- a closure or a nested function
- used to fulfill the cases
- when we need to provide some/few fixed parameters to any functions
- need to import
from functools import partial
partial
always takes functions as first parameter- e.g.
1 2 3 4 5 6 7 8 |
|
lambda
#
- format: lambda arg1, arg2, ...argN : expression using arguments
- anonymous function
- single-line
statementexpression - in-place function definition
- can be stored in a variable
- syntax:
Scopes:
1
lambda x: return x*x
- to make Jump Tables
- nested lambda
- loop in lambda using map()
map()#
- signature: map(aFunction, aSequence)
- applies a passed-in function to each item in an iterable object
- python2:returns a list containing all the function call results
- python3:returns an iterator of type map object
- Syntax
Out:
1 2
sqrs = list(map(lambda x: x*x, range(0,10))) print(sqrs)
1
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
filter()#
- signature: filter(aFunction, aSequence)
- applies a passed-in function to each item in an iterable object
- python2:returns a list of items for whose ** function call returns True**
- python3:returns an iterator of type map object for the items whose ** function call returns True**
- Syntax
Out:
1 2
evens = list(filter(lambda x: x%2 == 0, range(0,10))) print(evens)
1
[0, 2, 4, 6, 8]
reduce()#
(Dropped out in Python 3.x) * signature: filter(aFunction, aSequence) * applies a passed-in function to each item in an iterable object * python2:returns a single value * python3: dropped out
zip()#
1 2 3 |
|
Inverse a Matrix (list/tuple)#
1 2 3 4 5 6 |
|
Decorators#
- are a thin wrapper arround any function or any class
- there are also decorators for classes (read in Python-OOPs)
- benifits: do not need to decorate each method manually
- there are also decorators for classes (read in Python-OOPs)
-
when we apply a decorator to any function
- a few lines code in before start (if any) of the fuction call will get executed
- and/or a few lines code in after end (if any) of the fuction call will get executed
-
types of function decorator
- made out of a nested functions
- made out of a class
- decorator with param
- decorator over decorator
- order of decorators
-
Using
wraps
from functools- The way we have defined decorators so far hasn't taken into account that the attributes
1 2 3
__name__ (name of the function), __doc__ (the docstring) and __module__ (The module in which the function is defined)
of the original functions will be lost after the decoration.
-
simplest form of e.g. to create a custom decorator is:
1 2 3 4 5 6 7 8 9 |
|
Nested function#
1 2 3 4 5 6 7 8 |
|
Closures#
- is a concept - not a function
- a few may refer it as a nested function
- The local function is able to reference the outer scope through closures.
- Closures maintain references to objects from the earlier scope.
As per JavaScript#
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
Function Factory#
- these are functions that return other functions
- the returned functions are specialized
- Function Factory takes in argument(s), creates local function that creates its own argument(s) and also uses the argument(s) passed to the function factory
- this is possible with closures
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Parameter passing in python#
Passed As#
- by default, all the parameters (arguments) are passed âby referenceâ to the functions
- numbers, strings, tuples (i.e. immutables) are passed by value
Default Parameters#
- Non-default parameters comes before default parameters
- following will give
SyntaxError
1 2
def add(a, b=3, c): return a+b+c
1
SyntaxError: non-default argument follows default argument
Variable Number of Parameters#
*args
**kwarg
Exception Handling#
- Syntax:
1 2 3 4 5 6 7 8 9 10
try: # do something except IOError as e: # handle except ValueError: # handle except: # handle finally: # do final work
- can also put an else block after all the except block (will be executed if no exception occurs)
Inbuilt Exceptions#
- All the buil-in exceptions are subclass of
BaseException
AssertionError#
- raised when
assert
statement fails
AttributeError#
EOFError#
- raised when the
input()
function hits an end-of-file condition without reading any data
ImportError#
- raised when there is some trouble loading mudules
IndentationError#
- wrong indentation
IndexError#
- raised when a sequence is out of range
KeyError#
- when key not found in Dict
NameError#
- when a local or global name is not found
NotImplementedError#
- when a abstract/interface method lacks real implementation in sub-class
OSError#
- when there is some OS level failure like,
file not found
,disk full
RecursionError#
- when intrepreter detects maximum recursion depth
SyntaxError#
- when parser encounters some syntax error
1
print 1
1
SyntaxError: Missing parentheses in call to 'print'
TypeError#
- when an operation or function is applied to an inappropriate object
- e.g.
- when index is not an int
- addition of int + str
1
a = 1 + 'abc'
1
TypeError: unsupported operand type(s) for +: 'int' and 'str'
UnicodeError#
- when a unicode related encoding/decoding error occurs
ValueError#
- when a built-in operations or function receives an argument that has the right type but an inappropriate value.
1
int('abc')
1
ValueError: invalid literal for int() with base 10: 'abc'
ZeroDivisionError#
- when 2nd arg in division or modulo operation is zero
User-defined Exception#
- make a class
- inherit the
Exception
class - syntax:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Performance#
- https://wiki.python.org/moin/TimeComplexity
Misc#
is
vs ==
operator#
==
compares for values- i.e. checks that 2 arguments have the same value
1 2 3 4 5 6 7 |
|
is
checks ifoperand1
is exact copy ofoperand2
- i.e. checks that 2 arguments refer to the same object
1 2 3 4 5 6 7 |
|
Pickling Unpickling#
Pickling#
- python object hierarchy is converted into byte stream
- aka serialization, marshal, flattening
- can say 'binary serialization format'
- module:
pickle
Unpickling#
byte-like objects
orbinary files
are converted back into objects hierarchy- opposite of pickling
Comparision with JSON#
- JSON is a text serialization format
- it outputs unicode text, and most of the time it is then encoded to 'utf-8'
- JSON text is human readable which
pickle
is not - widely used outside the python, while pickle is python-specific
Monkey Patching#
- an evil hack ;)
- It's simply the dynamic replacement of attributes of a class/module at runtime.
- its possible because classes are mutable & methods are just attributes
- Also, we can replace classes and functions in a module
Uses#
- for testing purpose, replace a function which calls a heavy API with a dummy one
Code:
1 2 3 4 5 6 7 8 9 10 11 |
|
1 |
|
Duck Typing#
- EAFP: Easier to Ask Forgiveness than Permission
- Tag line definition: If an object can quack & fly, then its a duck.
- Do not worry about, if this object has this attribute or not, just try it inside try: block. If work then great, else handle the error.
- Opposite is LBYL: Look Before You Leap. (Check if it is possible or not, then try)
- e.g. https://gist.github.com/toransahu/337c287f8ead0d663c13b96d4b8fb7d2
Copy#
Regular Reference (Hard Copy)#
- Copies reference of original only not value.
- Changes in copy will also reflect in original. i.e. id of both would be same
** The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances) **
Shallow copy#
- A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
- Copies top level data & references other level objects into new
- Changes in top level not reflect in orignal
- Changes in other level objects reflect in orignal
Means ids of nested/child objects will remain same in both the copies
- doesn't slow downs programs
- refer example
Deep copy#
- A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the deforiginal.
- slow downs programs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Here, * values of l3 and l4 are same * but ids of l3 and l4 are different * nested/child object of l3 is not directly copied to l4 instead the reference of that child is provided. * the id of l3[1] & l4[1] are same, means changes in l4[0] will affect l3[0]. * sizes of l3 & l4 are different * sizes of l3[1] & l4[1] are different
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Except, * sizes of l3 & l4 are different * sizes of l3[1] & l4[1] are same
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Here, * values of l5 and l6 are same * but ids of l5 and l6 are different * nested/child object of l5 is directly copied to l6 instead of passing the reference * the id of l5[1] & l6[1] are different, means changes in l6[0] will not affect l5[0] * sizes of l5 & l6 are same * sizes of l5[1] & l6[1] are different
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Here, * Results are same as Manual Deep copy.
Except, * sizes of l5 & l6 are different * sizes of l5[1] & l6[1] are different
** Two problems often exist with deep copy operations that don’t exist with shallow copy operations: **
- Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
- Because deep copy copies everything it may copy too much, such as data which is intended to be shared between copies.