<jupyter_start><jupyter_text>Python Datatypes * **Numeric**    * **Integer**: Negative, zero, and positive number without decimal part Ex. ...-2,-1,0,1,2...    * **Float**: Decimal point numbers ...-2.1,-1.5,0.7,1.2,3.4...    * **Complex**: Number having both  *real number* and *imaginary number* $\sqrt{-1}$ Ex. 1+$\sqrt{-2}$ ⭐Integer Integral type is choosen by Py itself based on the magnitude.<jupyter_code>int() #default int() returns 0
a = 10  
b = -100
c = 0x14 #Octal
print(a,b)
print(c)  #Decimal
print(type(a))  #📌type() is an inbuilt function
print(type(b))
print(type(c)) 
a = 10
bin(a)
print('Binary to integer representation',0b1010)
hex(10)
print('Hexadecimal to integer representation',0xa)
oct(10)
print('Hexadecimal to integer representation',0o12)
a = 27
print('{} in decimal'.format(int(a)))
print('{} in hexadecimal'.format(hex(a)[2:]))
print('{} in binary'.format(bin(a)[2:]))
print('{} in octal'.format(oct(a)[2:]))
print('{} in decimal form to decimal: {}'.format('111',int('111',10)))
print('{} in hexadecimal form to decimal: {}'.format('1b',int('1b',16)))
print('{} in octal form to decimal: {}'.format('33',int('33',8)))
print('{} in binary form to decimal: {}'.format('11011',int('11011',2)))
a = 4.12
b = -4.99
c = '44'
print('a in integer form',int(a))
print('b in integer form',int(b))
print('c in integer form',int(c))
int('111001',2) #change default base to your desired base
int('111001',5)
a = 10
isinstance(a,int)
type(10)
int()
float()
str()
bool()
a = 5
b = 2

# Calculating Dividend & % 

a.__divmod__(b)
a = 3.2
a.__ceil__()
a.__floor__()
a = 5
b = 2
a.__floordiv__(b)
a.__truediv__(b)
a.__ge__(b)
a.__eq__(b)
a.__le__(b)
a.__ne__(b)
a.__neg__()
a.__bool__()
zero = 0
zero.__bool__()
b.__hash__()
a.__invert__()   # "plus 1 and change sign" - thank you Dr. <NAME>(MIET) for this memorable learning
~a
~a == a.__invert__()
a.__invert__().__invert__()
a.__lshift__(1)   # Multiplying by 2
a.__rshift__(1)
a.__mod__(2)
a.__mul__(3)
a.__xor__(2)
bin(a)[2:]
a.bit_length()
var = 1
var.__sizeof__()  #Number of bytes being used by this obj along with Garbage Collector overhead, in memory
'''
If MSB of an integer is not 0, it means that integer is negative
'''
bool(-16 >> 32 )<jupyter_output><empty_output><jupyter_text>⭐Float Precision akin to double in C++/Java<jupyter_code>float()
a = 10.1
b = -100.6
c = int(2e2) # 2 * 10^2
print('a is',a,'\nb is',b,'\nc is',c)  #Escape character(\n) for new line
print(type(a))
print(type(b))
print(type(c))
a = 1.211
print(pow(a,3))
print(round(a,2))
print(abs(a-3))
a = '1.2'
float(a)<jupyter_output><empty_output><jupyter_text>⭐Complex<jupyter_code>a = 1 + 2j
print(a)
print(type(a))<jupyter_output>(1+2j)
<class 'complex'><jupyter_text>* **Boolean**    * **True**(1)    * **False**(0) * All numbers results True if nonzero and False for if zero* Sequences and containers(viz list,string,tuple) results True if nonempty and False if empty* It is a default constructor of bool class<jupyter_code>1 == True
0 == False
1 == False
0 == True
x = True
print(type(x))
bool(1) #📌 bool() is an inbuilt function
bool() #default case
bool(0)
bool([1,2,3]) 
bool([])
bool((1,2,3,0))
bool('')
bool({})
bool({'filled':'yes'})<jupyter_output><empty_output><jupyter_text>* **Sequence**    * **String**: Collection of one or more than one characters in single quotes **' '** or double quotes **" "** and in triple quotes **''' '''** if the sentence is longer than one line. Strings are *immutable*.    * **List**: Unordered collection of data of any datatype. Lists are *mutable*.     * **Tuple**: Unordered collection of data of any datatype. Tuples are *immutable*. ⭐String * A string is a sequence of characters* It is immutable.* It compares two string character by character if there is any comparison task.* String in Python is based on **Unicode** international character set. * More internal compact representation than tuple/list<jupyter_code>"Hello" == 'Hello'  #lexographic comparison
'hello' == 'Hello'
str()
bool(str())
a = 'Hello, World!'
print(a)
print(type(a))
isinstance(a,str)
a = "Hello, World!" #📌String Indexing starts from 0 to n-1
a[2]
a[7:12] == a[7:-1]  
a[-2] #access the character from the last
#slicing of a string
a[0:5]
print(a[0:5],'Folk!')
a[7:-1]
#Concatenation
F_Name = 'Uditanshu'
L_Name = 'Saxena'
print(F_Name+' '+L_Name)
"Can't judge"  #here another quotation works as a string
'Can"t judge'  #here another quotation works as a string
'Can\'t judge'  #escape character \' is used
"Can\"t judge"
#Unicode characters in Python using \u
'\u20B9178' #\u20B9 ~ ₹
# Doc-string using ''' '''  or """ """
a = '''1. I am a programmer.
2. I am happy.
3. I enjoy writing incredible codes which help others. 
4. Coding in fun. '''
print(a)
a = 'hey'
a.upper() #📌built-in method
'HELLO'.lower()  #📌built-in method
a.isupper()  #📌built-in method
a.islower()  #📌built-in method
type(a)
len(a)  #📌built-in function
a = 'Vanijya Technology'
print(a.lower())
print(a.upper())
print(a.title())
print(a.swapcase())
" Yeah ".strip() #📌built-in method to remove whitespaces from left & right
" Yeah ".lstrip() #📌built-in method to remove whitespace from left
" Yeah ".rstrip() #📌built-in method to remove whitespace from right
" Hello ".strip().count('l') #📌built-in method to count number of specific character in a string
' hello'.endswith('lo') #📌built-in method to check if the string is ending with specified substring
'hello'.startswith('he') #📌built-in method to check if the string is starting with specified substring
'123'.isnumeric() #📌built-in method to check if the string is numeric
'hellpo '.isnumeric()
'hello'.isalpha() #📌built-in method to check if the string is alphabetic
'hello'.replace('llo','y') #📌built-in method to replace a substring from a string
a = " ".join(['Hey,','Deepak','Mittal']) #📌built-in method to join strings with a specified " " character
a
a.split() #default by whitespace
'Hello'.find('e')
'Hello'.index('e')
'Hello'.replace('ll','oo😂')
a = 'Hello'
b = 'Hello'
print(a is b) #Compare lexicographically
print(a == b)<jupyter_output>True
True<jupyter_text>🧐Formating in string<jupyter_code>'My name is {} and I have {} computers'.format('<NAME>',2)
#https://docs.python.org/3/library/string.html#format-specification-mini-language
'My name is {name} and I have {number} computers'.format(number = 2,name = "<NAME>")
'My name is {1} and I have {0} computers'.format(2,"<NAME>")
'{:.2s} is awesome'.format('Python')
'{:<6s}'.format('hi') #left alignment
'{:>6s}'.format('hi')  #right alignment
'{:^6s}'.format('hi')       #center alignment
format(121, "d")
format(121, ".2f"),format(12, "f")
format(15, "b")
format(-11, "b")
format(1561, "*>+7,d")
format(566.7883, "^-09.3f")
x = 10.5
y = x * 1.1

'Number {:.2f} and with 10% additional is {:.2f}'.format(x,y)
s = '20\u20AC'  # Unicode international character set
s<jupyter_output><empty_output><jupyter_text>⭐List Python is build using C-programming. List is the most general usuable sequence in Python. However, internally it is based on the array datatype of C-programming. When a list is instantiated, an array is instantiated under the hood. An array under the list tends to have many unoccupied positions which results in the unnecessary occupancy of memory. When an element is added to the list, it get added at the empty space. But when new elements are adding even more than the size of entire array, following process happens:* The new array with larger size is instantiated corresponding to the size of previous array but the exact dimension is fuzzy. * All the elements are copied to the new array. * Old array deleted. * New elements are then appended to the new array. When the elements from the list is removed, it tends to contract its size generally after around half of the positions are unoccupied. -----------------------------------------------------------------------* Lists are mutable* It is a referential structure(a[0],a[1],... reference to a particular element)* It is zero-indexed. * It can dynamically expand and contract its size depending upon the requirement and using above mechanism⬆.  * It uses [ ] as delimiters for literals.<jupyter_code>a = [] #empty list
a = list() #constructor for an empty list
print(type(a))
a = []
isinstance(a,list)
list('Python')
temp = [1,23,4,3.4, 4.5,'Nandini',["ismaa",'Learning Python']]
temp[5] = "jvala" #📌Mutability 
temp
temp[6][0][2:]
temp[6][1][-6:-4]
var = temp[6][0]
var[1:3]
a = ['a','b',34,[23,3],'Hello, World!']
print(a)
a[1]
a[3]
a[3][1]
a[4][7]
a[4][12] == a[4][-1]
a[4][0:5] #📌slicing
len(a)
temp = [38,39,33,37,32,50]
print(min(temp)) #📌built-in function
print(max(temp))
[1,2,3,4] + [2,2,2,2] #concatenation
'a' in a 
a.append('d')  #📌built-in method which is use to add a element at the end of list
a
a.index('d') #this method is called "accessors" because it does not change the state of an object
a
a[3][1] = 'Piyush'  #📌 Lists are mutuable
a
a.index('d')
a = [1,2,3]
b = [4,5,6]
c = [*a,*b,7,8,9] #spreading
print(c)

del c[1]
print(c)
c.insert(0,10)
print(c)

print(c.index(6))

c.remove(9)
print(c)

c.sort() #Permanent sorting
#this method is called mutators(or update methods) because it changes the state of an object
c.sort(reverse=True)  #TC - O(NlogN)

d = c.copy() #preventing the duplication of pointer to memory address
e = c[:] #alternate method of above

print(d)
print(e)
a = [1,2,3,4,5]
b = [1,2]
c = [4,5]
print(a >= b) #compare lexicographically
print(a > b)  #compare lexicographically
print(c > a)  #compare lexicographically
a = [1,2,3,4,5]
b = a   #Aliased
b += [6,7,8,9]  #Note - Alias not broken
print(b)
print(a)
a = [1,2,3,4,5]
b = a   #Aliased
b = b + [6,7,8,9]  #Note - Alias broken💔
print(b)
print(a)<jupyter_output>[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5]<jupyter_text>⭐Tuple * It is also a sequence datatype of Python* It uses ( ) as delimiter* It is immutable - Internal representation is more streamlined than that of a list.<jupyter_code>tuple() #default tuple
type((1))
type((1,)) #Notice the difference with comma   
a = 1, #one-element tuple
type(a)
a
isinstance(a,tuple)
tup = (1,2,3,4)
tup
tup[0]
tup[0] = "Laptop"   #📌 tuples are immutuable 📌Error because tuple is immutable
t = (1,2,3,4) #create tuple
t = list(t)   # convert tuple into list using list() function
t.append(5)  # add 5 in list t [1,2,3,4,5]
t = tuple(t)  # convert into tuple using tuple() function
t
len(t)
a = (1,2,3)
b = (4,5,6)
c = (*a,*b,7,8,9) #spreading
print(c)<jupyter_output>(1, 2, 3, 4, 5, 6, 7, 8, 9)<jupyter_text>⭐SetUnordered collection of objects to perform mathematical set operation. Contains only unique items. Optimized as compared to a list and based on hash table data structure.Contains immutable elements but itself is mutableTC to access an element in a set is O(1) vs O(N) in list<jupyter_code>a = set()  #constructor set()
print(type(a))

a = {}
print(type(a))
a = {1,2,3}
type(a)
a = 'Python'
set(a) #unordered
a = {1,2,3,4,5}
b = {4,5,6,7,7}  # 7 twice
print(a)
print(b) #printed only once because set do not contain two similar elements
#OR
a | b 
#union
print(a.union(b)) #a u b
print(b.union(a)) #b u a
#AND
a & b
#intersection
print(a.intersection(b))
print(b.intersection(a))
#difference
print(a-b)
print(a.difference(b))
print(b-a)
print(b.difference(a))
#symmetric difference
print(a ^ b)
print(a.symmetric_difference(b))
print(b ^ a)
print(b.symmetric_difference(a))
print(a)
a.add(8)
print(a)

a.discard(1)
print(a)

a.remove(2)
print(a)
#remove raises an error if element is not in the set but discard do not
a.add([1,2]) #set contains only immutable items not mutable; raise error
a.add({1,2}) # a set is also mutable; raise error
a.add((1,2))
print(a)

a.add('hello')
a
#adding multiple elements
a.update([9,19,17]) #here we are not adding a list instead multiple elements
a
s = {1,2,3,4,5,6}
s.pop() #removing a random element; mutator-method
s 
s = {1,2,3,4,5,6}
s.clear()
s
s = {1,2,3,4,5,6}
t = s.copy()
print(t)

t.pop()
print(t)

print(t.difference(s))
print(s.difference(t))
s = {1,2,3,4,5,6}
t = {10}
u = {1,2}

print('Is t and s are dis-joint sets?',t.isdisjoint(s))
print('Is u a subset of s?',u.issubset(s))
print('Is s a superset of u?',s.issuperset(u))
a = {1,2,3}
b = 1
c = {1,2,3}
d = {1,2}

print(b in a) 
print(b not in a)
print('a and c are equivalent?',a == c) #both are equivalent because of having same elements
print('a and c are not equivalent?',a != c)
print('d is subset of a?',d <= a) #not lexicographic comparison
print('d is proper subset of a?',d < a)
print('a is superset of c',a >= c)
print('a is proper superset of d',a>d)
print('union of a and d',a|d)
print('intersection of a and d',a&d)
print('a is superset of b?',a )<jupyter_output>True
False
a and c are equivalent? True
a and c are not equivalent? False
d is subset of a? True
d is proper subset of a? True
a is superset of c True
a is proper superset of d True
union of a and d {1, 2, 3}
intersection of a and d {1, 2}
a is superset of b? {1, 2, 3}<jupyter_text>**Frozenset** - A special type of set which is immutable.<jupyter_code>a = frozenset([1,2,3,4])
type(a)<jupyter_output><empty_output><jupyter_text>⭐DictionaryStore data in the form of Key-value pairs<jupyter_code>d = {}        #dictionary declaration not a set declaration. 
d = dict()    #Another way of declaring a dictionary.      

d = {'one':['isma','nandini','piyush'],'two':2.0,'three':3,5:5.0}
d
d['two']
d['four'] = 4
d['five'] = 5
d
d.keys() #📌built-in method to get all the keys
d.values()  #📌built-in method to get all the values
d.items() #📌built-in method to get all items in form of list of tuples
d.pop('two') #📌built-in method to remove any pair
d
d1 = {1:'yes',2:'no'}
d2 = {1:'hello',2:'viola'}
d3 = {2:'no',1:'yes',}

print('1 in d1?',1 in d1)
print('1 not in d1?', 1 not in d1)
print('d1 == d2?', d1 == d2) #compare both key-value non-lexicographically
print('d1 != d2?', d1 != d2)
print('d1 == d3?', d1 == d3)
print('d1 != d3?', d1 != d3)<jupyter_output>1 in d1? True
1 not in d1? False
d1 == d2? False
d1 != d2? True
d1 == d3? True
d1 != d3? False<jupyter_text>Aliasing in Python</h2<jupyter_code>a = 2
b = a 
b
b = 3
a<jupyter_output><empty_output><jupyter_text>- Aliasing in Python works until there is no additional value assignment to the alias. Assignment to any alias breaks the alaising and will not affect other identifiers.- `is` is use if we explicitly what to check true alaising<jupyter_code>a = 1
b = a
c = b
c
a = 4
c
a = 1
c = a
c *= 2
print(a,c)
a = 2
b = a
a is b
a = 2 
b = 2
a is b
a = 256  #extreme point for aliasing
b = 256
a is b
a = 257
b = 257
a is b
a = 0
b = 0
a is b
a = -5 #extreme point for aliasing(-5 to 256)
b = -5
a is b
a = -6
b = -6
a is b<jupyter_output><empty_output><jupyter_text>However, using == and != we can find out whether both identfiers are equivalent upto any extend.<jupyter_code>a = 10000
b = 10000
a == b
a = [2,4,6,8]
b = a
b += [10,12] #still alias
print(a)
print(b)
a = [2,4,6,8]
b = a
b = b + [10,12] #alias breaked; carefully look at the difference in both assignments
print(a)
print(b)
a = [2,4,6,8]
b = a[:]  #no alias at all
b += [10,12] 
print(a)
print(b)
a = [2,4,6,8]
b = a.copy()  #no alias at all
b += [10,12] 
print(a)
print(b)
1 in range(7)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1701386607084182, 'fraction_numerical': 0.04002102911217717, 'mean_word_length': 4.638384586884031, 'pattern_counts': {'":': 0, '<': 60, '<?xml version=': 0, '>': 65, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '286899', 'license': 'MIT', 'n_tokens_mistral': 6150, 'n_tokens_neox': 5859, 'n_words': 1967, 'path': '01 - Basics/02-DataType.ipynb', 'repo_name': 'yesdeepakmittal/PY_training', 'size': '15244'}