Chapter 2_Core Data Types
I. Strings:
1. Basics:
a = "Hello" <=> 'Hello'
b = """Lorem ipsum dolor sit amet,
consectetur adipiscing elit """ # Multiple line str
print(a[1]) # # Strings are sequences (indexable & iterable)
2. Access:
2.1 Indexing:
x = 'abc'
print(x[0]) # a
2.2 Slicing
b = "Hello, World!"
print(b[2:5]) # llo
print(b[:5]) # Hello
print(b[2:]) # llo, World!
print(b[-5:-2]) # orl
2.3 Membership
thing in stringVar
thing not in smth
2.4 Length:
len(str1)
3. Modification:
3.1 concatenation:
a = "Hello"
b = "World"
c = a + " " + b
print(c) # Hello World
3.2 builtin-methods:
a = "Hello, World!"
print(a.upper()) # HELLO, WORLD!
print(a.lower()) # hello, world!
print(a.strip()) # removes whitespace
print(a.replace("H", "J")) # Jello, World!
print(a.split(",")) # ['Hello', ' World!']
print(a.find(',')) # returns the position of `,` (first occurence) (-1 -> element not found)
3.3 Essential String Methods
upper(), lower(), capitalize()
startswith(), endswith()
split(c) # splits from the left, c = seperator char, whitespace (default)
rsplit() # Default separator = whitespace
strip(c), rstrip(), lstrip() # default is whitespace
index()
count()
replace(a, b)
find(smth)
4. f-string:
x = 1
print(f"Value is {x}")
x = 32
f"Value {x}" # placeholder {}
f"Result {1+2}" # expression
# modifier ( A modifier is included by adding a colon `:` followed by a legal formatting type, like `.2f`)
price = 59
txt = f"The price is {price:.2f} dollars"
5. Raw Strings & Regex:
✅ Regex = raw string + re functions
"\\d+" # ❌ interpreted by Python
r"\\d+" # ✅ correct for regex
print(r"C:\new\folder") # raw string
II. Booleans:
1. Most Values are True
✅ True:
- Non-empty strings
- Non-zero numbers
- Non-empty lists, tuples, sets, dicts
❌ False:
False <=> None, 0, "", (), [], {}
2. Custom len Example
👉 Objects with __len__() that returns 0 or False evaluate to False
class myclass():
def __len__(self):
return 0
myobj = myclass()
print(bool(myobj)) # False
III. Operators:
1. Arithmetic Operators
# Binary Operators:
x + y # Addition
x - y # Subtraction
x * y # Multiplication
x / y # Division
x % y # Modulus
x ** y # Exponentiation
x // y # Floor division
# Unary Operators: (+/-) (signes)
+1, -1
2. Assignment Operators
=, +=, -=, *=, /=, %=, //=, **=, &=, |=, ^=, >>=, <<=, := ( walrus operator )
Note (Walrus operator):
In Python, conditions allow expressions only, not statements.
❌ Invalid:
if x = 3: pass
:=evaluates an expression, assigns it to a variable, and returns the valueif (n := len(data)) > 10: print(n)
3. Comparison Operators
==, !=, >, <, <=, >=
Python allows chaining comparison operators:
( 1 < x < 10 ) <=> ( 1 < x and x < 10 )
4. Logical Operators
and, or, not
5. Identity Operators
is not
is : returns true if both vars points to the same object
6. Membership Operators
in, not in
7. Bitwise Operators:
& : bitwise and
| : bitwise or
^ : xor
~ : bitwise not
x<<n : left shift (adding n 0 )
x>>n : right shift
8. Python Operator Precedence:
()
**
+ - ~ : unary
* / // %
+ - : binary
<< >>
&
^
|
comparisons, identity, membership
not
and
or
# same order => L -> R evaluation
9. Special unary operator: (Asterisk *)
- Using * and ** to pass arguments to a function
- Using * and ** to capture arguments passed into a function
- Using * to accept keyword-only arguments
- Using * to capture items during tuple/list unpacking
- Using * to unpack iterables into a list/tuple
- Using ** to unpack dictionaries into other dictionaries
- More details
- etc
When
*and**CAPTURE values:
*collects positional values
- →
tuplein function definitions (*args)- →
listin assignment unpacking (a, *b = ...)
**collects keyword values ( it always produces a dict )
- →
dictin function definitions (**kwargs)
1) Using * and ** to pass arguments to a function
* for positional arguments
fruits = ['lemon', 'pear', 'tomato']
print(*fruits)
This sends each item in the list as a separate positional argument.
** for keyword arguments
date_info = {'year': '2020', 'month': '01'}
"{year}-{month}".format(**date_info)
This sends each key/value pair as a named argument.
Python 3.5+ even allows multiple
*or**in a call:print(*nums, *fruits)
2) Using * and ** to capture arguments passed into a function
*args _ capture any number of positional arguments
def roll(*dice):
...
Here dice becomes a tuple of all extra positional args.
**kwargs — capture keyword arguments
def tag(name, **attributes):
...
attributes becomes a dictionary of extra named args.
3) Using * to accept keyword-only arguments
If you place a * alone in a function signature, all following parameters must be passed by name:
def get_multiple(*keys, dictionary, default=None):
...
Here dictionary and default cannot be passed positionally.
This mechanism is used in built-in functions like sorted to make some parameters keyword-only.
4) Using * to capture items during tuple/List unpacking
Python lets you use * in assignments to grab multiple items:
first, *rest = fruits
rest becomes a list of the remaining items.
This also works between variables:
first, *middle, last = fruits
Only one * expression is allowed at a given unpacking level.
5) Using * to unpack iterables into a list/tuple
Python 3.5+ allows you to “dump” items from an iterable into a new list, tuple, or set:
[*sequence, *reversed(sequence)]
This is a powerful alternative to chaining with + or converting manually.
You can also unpack into tuples and sets:
(*fruits[1:], fruits[0])
{*fruits, *uppercase_fruits}
6) Using ** to unpack dictionaries into other dictionaries
Python 3.5+ lets you expand key/value pairs from one or more dicts into a new dict:
all_info = {**date_info, **track_info}
You can also merge with additional keys and override values.
7) More details:
-
7.1) Function Parameter Boundaries
(*, *args, /)Definition Effect def f(a, b, *, c, d)c, d→ keyword-onlydef f(a, *b, c, d)c, d→ keyword-onlydef f(a, b, /, c, d)a, b→ positional-only -
7.2)
*in function calls force positional evaluation order
def f(a, b, c):
...
args = (1, 2, 3)
f(*args) # positional mapping happens left → right
f(*args, c=5) # ❌ multiple values for c
- 7.3)
**cannot capture non-string keys
{**{1: "a"}} # ❌ TypeError
- 7.4)
*unpacking works in return statements
def f():
return *range(3), 10
# Equivalent to returning a tuple: (0, 1, 2, 10)