# This is a single-line comment ''' This is a multi-line comment Line 1 Line 2 '''
my_list = [1, 2, 3] my_tuple = (4, 5, 6) my_list[0] = 10 # Valid, modifies the list # my_tuple[0] = 10 # Invalid, will raise an error
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
A decorator is a function that takes another function as its input and returns a new function. The new function is a wrapper around the original function.
def debug(func):
def wrapper(*args, **kwargs):
print('Calling {}'.format(func.__name__))
return func(*args, **kwargs)
return wrapper
@debug
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
print(factorial(5))
x = [1, 2, 3] y = x print(x is y) # True print(x == y) # True z = [1, 2, 3] print(x is z) # False print(x == z) # True
lambda keyword. They are typically used for short, simple tasks.
add = lambda x, y: x + y print(add(2, 3)) # Output: 5
squares = [x ** 2 for x in range(1, 6)] print(squares) # Output: [1, 4, 9, 16, 25]
A comprehension is a concise way to create a list, set, or dictionary. Comprehensions are often used to filter or transform a sequence of values.
even_numbers = [i for i in range(10) if i % 2 == 0]
squares = {i ** 2 for i in range(10)}
names_and_ages = {name: age for name, age in zip(['John', 'Jane', 'Mary'], [30, 25, 40])}
try block contains the code that may raise an exception, and the except block handles the exception if it occurs.
try:
num = int(input("Enter a number: "))
result = 10 / num
except ZeroDivisionError:
print("Error: Cannot divide by zero.")
except ValueError:
print("Error: Invalid input. Please enter a number.")
else:
print("Result:", result)
finally:
print("Execution completed.")
yield keyword to return an iterator, allowing you to iterate over a sequence of values without generating the entire sequence at once.
def countdown(n):
while n > 0:
yield n
n -= 1
for i in countdown(5):
print(i)
5 4 3 2 1
A generator is a function that can be used to iterate over a sequence of values. Generators are often used to create iterators, which are objects that can be used to iterate over a sequence of values.
def fibonacci(n):
a, b = 0, 1
for i in range(n):
yield a
a, b = b, a + b
for i in fibonacci(10):
print(i)
__str__ and __repr__?__str__ is used to provide a user-friendly string representation of an object, while __repr__ is used to provide a developer-friendly string representation, often used for debugging.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name}, {self.age} years old."
def __repr__(self):
return f"Person('{self.name}', {self.age})"
person = Person("Alice", 30)
print(str(person)) # Output: Alice, 30 years old.
print(repr(person)) # Output: Person('Alice', 30)
if x < 0:
pass # Placeholder for handling negative numbers
else:
print("Positive number")
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print('Hello, my name is {}'.format(self.name))
person = Person('John Doe', 30)
person.say_hello()
class Animal:
def __init__(self, name):
self.name = name
def make_sound(self):
print('I am an animal!')
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
def bark(self):
print('Woof!')
class Cat(Animal):
def __init__(self, name, fur_color):
super().__init__(name)
self.fur_color = fur_color
def meow(self):
print('Meow!')
dog = Dog('Sparky', 'Golden Retriever')
dog.bark()
cat = Cat('Mittens', 'Black')
cat.meow()
with open("example.txt", "r") as file:
data = file.read()
# The file is automatically closed after exiting the 'with' block
copy module or using the slice operator.
import copy # Shallow copy using copy module original_list = [1, 2, 3] copied_list = copy.copy(original_list) # Deep copy using copy module original_list = [1, [2, 3], 4] copied_list = copy.deepcopy(original_list) # Shallow copy using slice operator original_list = [1, 2, 3] copied_list = original_list[:]
class A:
def method_a(self):
print("Method A")
class B:
def method_b(self):
print("Method B")
class C(A, B):
pass
obj = C()
obj.method_a() # Output: Method A
obj.method_b() # Output: Method B
open() to open a file and perform operations like reading, writing, or appending data.
# Writing to a file
with open("data.txt", "w") as file:
file.write("Hello, World!")
# Reading from a file
with open("data.txt", "r") as file:
content = file.read()
print(content) # Output: Hello, World!
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
def test_factorial():
# Create a mock object that simulates the behavior of a real function.
mock_factorial = mock.Mock()
mock_factorial.return_value = 120
# Use the mock object to test the factorial function.
assert factorial(5) == mock_factorial.call_count
# Create a stub object that provides canned responses to requests.
stub_factorial = stub.Stub()
stub_factorial.return_value = 120
# Use the stub object to test the factorial function.
assert factorial(5) == stub_factorial.return_value
unittest and pytest:
unittest uses a more verbose syntax than pytest. For example, unittest requires you to explicitly define a class for each test case, while pytest allows you to define test cases directly in functions.unittest does not have a built-in fixture system, while pytest does. Fixtures are reusable bits of code that can be used to set up or tear down your tests.unittest and pytest both have assertion libraries, but pytest‘s assertions are more concise and expressive. For example, unittest requires you to use the assertEqual() method to compare two values, while pytest allows you to use the more expressive assert statement.pytest has a plugin system that allows you to extend its functionality. There are many plugins available for pytest, including plugins for generating test reports, collecting code coverage data, and running tests in parallel.In general, pytest is a more modern and expressive testing framework than unittest. However, unittest is still a widely used testing framework, and it may be a better choice for some projects.
A CI server is a tool that automates the process of continuous integration. A CD server is a tool that automates the process of continuous delivery.
Here is an example of how a CI server and a CD server can be used together:
Microservice architecture is more scalable and flexible than monolithic architecture. However, it can be more complex to develop and maintain.
Here is an example of how a microservice architecture and a monolithic architecture can be used:
RESTful APIs are more lightweight and easier to use than SOAP APIs. However, SOAP APIs can be more powerful and can support more complex data types.
Here is an example of how a RESTful API and a SOAP API can be used:
JSON APIs are more lightweight and easier to use than XML APIs. However, XML APIs can be more powerful and can support more complex data types.
Here is an example of how a JSON API and an XML API can be used:
from flask import Flask
app = Flask(__name__)
@app.route('/users', methods=['GET'])
def get_users():
"""Get a list of all users."""
users = [
{'id': 1, 'name': 'John Doe'},
{'id': 2, 'name': 'Jane Doe'},
]
return jsonify(users)
@app.route('/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
"""Get a specific user by ID."""
user = {'id': user_id, 'name': 'John Doe'}
return jsonify(user)
if __name__ == '__main__':
app.run(debug=True)
This code defines two RESTful APIs:
/users: This API returns a list of all users./users/<int:user_id>: This API returns a specific user by ID.The GET method is used to retrieve data from the API, the POST method is used to create new data, the PUT method is used to update existing data, and the DELETE method is used to delete data.
The data returned by the API is in JSON format. JSON is a lightweight data-interchange format that is easy to read and write.
query {
user(id: 1) {
name
age
}
}
A RESTful API might use the following HTTP requests to fetch the same data:
GET /users/1 GET /users/1/name GET /users/1/age
In general, GraphQL APIs are a good choice for applications where the data is the most important part of the API. RESTful APIs are a good choice for applications where the resources are the most important part of the API.
Here is a table that summarizes the key differences between GraphQL APIs and RESTful APIs:
| Feature | GraphQL API | RESTful API |
|---|---|---|
| Querying | Single query language | Different verbs for different types of requests |
| Data fetching | Clients specify exactly the data that they need | Clients fetch all of the data for a resource |
| Data modeling | Data-driven | Resource-driven |
| Complexity | More complex to develop | Less complex to develop |
| Best for | Applications where the data is the most important part of the API | Applications where the resources are the most important part of the API |
P
Data serialization is the process of converting structured data to a format that allows sharing or storage of the data in a form that allows recovery of its original structure. In some cases, the secondary intention of data serialization is to minimize the data’s size which then reduces disk space or bandwidth requirements.
It’s common to transmit and receive data between a server and web application in JSON format.
john = {"name":"Folau","age":30}
jjohn = json.dumps(john, indent = 2, sort_keys=True)
print(jjohn)