# 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)