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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
| #!/usr/bin/env python3
"""Example module showing PEP 8 style guidelines.
This docstring follows PEP 257 guidelines:
- Starts with a one-line summary
- Followed by a blank line
- More detailed description
"""
# ==========
# Imports are grouped in the following order:
# 1. Standard library imports
# 2. Related third party imports
# 3. Local application/library specific imports
# ==========
import os # Standard library imports are listed first
import sys
from datetime import datetime
from typing import Dict, List, Optional, Union # Multiple imports from same module
import numpy as np # Third party imports after a blank line
import requests
from fastapi import FastAPI # Imports are in alphabetical order
from my_module import my_function # Local imports after another blank line
# ==========
# Constants
# - Use UPPER_CASE
# - Define at module level
# ==========
MAX_CONNECTIONS = 100
DEFAULT_TIMEOUT = 30
# ==========
# Classes
# - Use CapWords convention
# - Two blank lines before class definition
# ==========
class DatabaseError(Exception):
"""Custom exception class following PEP 8.
- Class docstring indented at same level as class code
- Inherits from appropriate base class (Exception)
"""
pass
class UserProfile:
"""Class demonstrating PEP 8 class formatting guidelines."""
# Class attributes are defined at the top
default_settings = {
'timeout': DEFAULT_TIMEOUT, # Dictionary formatted with space after :
'retry_count': 3,
'max_attempts': 5
}
def __init__(
self, # Long parameter lists can be indented
username: str, # Type hints used for parameters
email: str,
*, # Enforce keyword-only arguments
is_active: bool = True # Default values after type hints
) -> None: # Return type hint
"""Initialize UserProfile.
Args:
username: The user's username
email: The user's email
is_active: User's active status
"""
# Validate parameters before assignment
if not username or not email:
raise ValueError(
"Username and email must not be empty" # Line breaking before operators
)
# Protected attributes start with single underscore
self._username = username
self._email = email
# Private attributes start with double underscore
self.__password_hash = None
# Public attributes without underscore
self.is_active = is_active
self.created_at = datetime.now()
def get_profile_data(self) -> Dict[str, Union[str, datetime]]:
"""Get user profile data.
Returns:
Dictionary containing user profile information
"""
# Return dictionary with consistent formatting
return {
'username': self._username,
'email': self._email,
'created_at': self.created_at,
'is_active': self.is_active
}
def _validate_password(self, password: str) -> bool:
"""Protected method for password validation.
Args:
password: Password to validate
Returns:
Boolean indicating if password is valid
"""
# Use inline comment only for complex logic
return bool(password and len(password) >= 8) # Minimum length check
# ==========
# Functions
# - Use snake_case for function names
# - Two blank lines before function definitions
# ==========
def calculate_user_statistics(
users: List[UserProfile],
*, # Enforce keyword-only arguments
include_inactive: bool = False, # Default value
max_count: Optional[int] = None # Optional parameter type
) -> Dict[str, int]: # Return type annotation
"""Calculate user statistics.
Args:
users: List of user profiles
include_inactive: Whether to include inactive users
max_count: Maximum number of users to process
Returns:
Dictionary with user statistics
"""
# Use meaningful variable names
total_users = len(users)
active_users = sum(1 for user in users if user.is_active)
# Dictionary proper formatting
stats = {
'total_users': total_users,
'active_users': active_users
}
# Explicit is better than implicit
if include_inactive:
stats['inactive_users'] = total_users - active_users
return stats
def process_data(
data: List[Dict[str, Union[str, int]]], # Complex type hints
**kwargs: Dict[str, any] # Variable keyword arguments
) -> List[Dict[str, Union[str, int]]]:
"""Process input data with optional parameters.
- Docstring uses proper indentation
- Args and Returns sections properly formatted
"""
try:
# Good: Use meaningful temporary variable names
processed_data = []
# Good: Explicit iteration over sequence
for item in data:
if _should_process_item(item): # Protected function call
processed_item = _process_single_item(item)
processed_data.append(processed_item)
except Exception as e:
# Good: Exception variable named 'e'
# Good: Error message uses string formatting
print(f"Error processing data: {str(e)}", file=sys.stderr)
raise
return processed_data
# Protected functions start with underscore
def _should_process_item(item: Dict[str, any]) -> bool:
"""Check if item should be processed."""
# Good: Return boolean conditions directly
return bool(item and item.get('active', True))
def _process_single_item(item: Dict[str, any]) -> Dict[str, any]:
"""Process a single item."""
# Good: Create new dictionary instead of modifying input
return {
**item,
'processed': True,
'processed_at': datetime.now()
}
# ==========
# Main execution block
# - Two blank lines before
# - Proper if __name__ == '__main__' block
# ==========
if __name__ == '__main__':
# Example usage
users = [
UserProfile(
username='user1',
email='user1@example.com',
is_active=True
),
UserProfile(
username='user2',
email='user2@example.com',
is_active=False
)
]
# Good: Use keyword arguments for clarity
stats = calculate_user_statistics(
users=users,
include_inactive=True
)
# Good: Use f-strings for string formatting
print(f"User statistics: {stats}")
# Good: Line breaking before binary operators
total_active_users = (
stats['total_users']
- stats.get('inactive_users', 0)
)
# Good: Consistent spacing in expressions
if total_active_users > 0 and stats['total_users'] < MAX_CONNECTIONS:
print("System is operating within normal parameters")
|