Skip to content

Commit aabbfe0

Browse files
Manual review of builtin functions: next-locals
Mostly removing content that has nothing to do with performance.
1 parent 433f7ad commit aabbfe0

3 files changed

Lines changed: 12 additions & 288 deletions

File tree

docs/builtins/globals.md

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -138,27 +138,6 @@ def func():
138138
func()
139139
```
140140

141-
### Nested Functions
142-
143-
```python
144-
# Nested functions can access enclosing scope
145-
def outer():
146-
x = 10
147-
148-
def inner():
149-
y = 20
150-
151-
# locals() shows only inner's variables
152-
print(locals()) # {'y': 20}
153-
154-
# Access outer's x through closure, not locals()
155-
print(x) # 10 (from enclosing scope)
156-
157-
inner()
158-
159-
outer()
160-
```
161-
162141
## Modifying Namespaces
163142

164143
### Setting Global Variables
@@ -303,76 +282,6 @@ for i in range(10000):
303282
my_data[f'var_{i}'] = i # O(1) each
304283
```
305284

306-
## Advanced Patterns
307-
308-
### Inspecting Function Parameters
309-
310-
```python
311-
import inspect
312-
313-
def my_func(a, b, c=10):
314-
# Get function signature
315-
sig = inspect.signature(my_func) # O(1)
316-
317-
# Get local variables
318-
local_vars = locals() # O(m)
319-
320-
# Show what was passed
321-
params = {}
322-
for param_name in sig.parameters: # O(k) params
323-
params[param_name] = local_vars.get(param_name)
324-
325-
return params
326-
327-
result = my_func(1, 2, 3) # O(m)
328-
print(result) # {'a': 1, 'b': 2, 'c': 3}
329-
```
330-
331-
### Metaprogramming
332-
333-
```python
334-
# Create class dynamically - O(k)
335-
def create_class(name, attrs):
336-
"""Create class using globals()"""
337-
class_dict = {} # O(1)
338-
339-
for attr_name, attr_value in attrs.items():
340-
class_dict[attr_name] = attr_value
341-
342-
# Create class (simplified)
343-
return type(name, (), class_dict)
344-
345-
MyClass = create_class('MyClass', {'x': 10, 'y': 20})
346-
obj = MyClass()
347-
print(obj.x) # 10
348-
```
349-
350-
## Debugging with Frame Inspection
351-
352-
```python
353-
import inspect
354-
355-
def get_caller_info():
356-
"""Get information about calling function"""
357-
current = inspect.currentframe() # O(1)
358-
frame = current.f_back if current is not None else None # O(1)
359-
if frame is None:
360-
return None
361-
362-
# Access caller's locals - O(m)
363-
locals_dict = frame.f_locals
364-
365-
return {
366-
'line': frame.f_lineno,
367-
'locals': locals_dict
368-
}
369-
370-
def example():
371-
x = 10
372-
y = 20
373-
# info = get_caller_info() # O(m)
374-
```
375-
376285
## Version Notes
377286

378287
- **Python 2.x**: Same behavior
@@ -384,18 +293,3 @@ def example():
384293
- **[vars()](vars.md)** - Similar to locals() but for objects
385294
- **[dir()](dir.md)** - List names in namespace
386295
- **inspect.signature()** - Get function signature
387-
388-
## Best Practices
389-
390-
**Do**:
391-
392-
- Use `globals()` for metaprogramming when needed
393-
- Use inspect module for reflection
394-
- Be explicit about variable scope
395-
396-
**Avoid**:
397-
398-
- Relying on locals() to set variables in functions
399-
- Modifying globals() at module level (confusing)
400-
- Using globals()/locals() instead of proper parameters
401-
- Assuming locals() state persists after function returns

docs/builtins/id.md

Lines changed: 2 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -48,55 +48,12 @@ print(x is z) # False - different objects
4848
print(id(x) == id(z)) # False - different IDs
4949
```
5050

51-
## Understanding Python Objects
52-
53-
### Immutable Types
54-
55-
```python
56-
# In CPython, small integers are cached (implementation detail)
57-
a = 5
58-
b = 5
59-
print(id(a) == id(b)) # True - same cached object
60-
61-
# For larger integers, identity behavior is implementation/code-path dependent
62-
c = int("257")
63-
d = int("257")
64-
print(id(c) == id(d)) # Typically False (distinct runtime-created objects)
65-
66-
# String interning (same for equal strings sometimes)
67-
s1 = "hello"
68-
s2 = "hello"
69-
print(id(s1) == id(s2)) # Usually True (interned)
70-
71-
t1 = "".join(['h', 'e', 'l', 'l', 'o'])
72-
t2 = "".join(['h', 'e', 'l', 'l', 'o'])
73-
print(id(t1) == id(t2)) # False (not interned)
74-
```
75-
76-
### Mutable Types
77-
78-
```python
79-
# Lists create new objects - O(1) to get ID
80-
lst1 = [1, 2, 3]
81-
lst2 = [1, 2, 3]
82-
print(id(lst1) == id(lst2)) # False - different objects
83-
84-
# Assignment creates reference, not copy
85-
lst3 = lst1
86-
print(id(lst1) == id(lst3)) # True - same object
87-
print(lst1 is lst3) # True
88-
89-
# Modification affects both
90-
lst3.append(4)
91-
print(lst1) # [1, 2, 3, 4] - both modified
92-
```
93-
9451
## Common Patterns
9552

9653
### Checking Object Identity
9754

9855
```python
99-
# Use is/is not instead of id() directly - cleaner
56+
# Use is/is not instead of id() directly - cleaner and faster
10057
x = [1, 2, 3]
10158
y = x
10259
z = [1, 2, 3]
@@ -108,7 +65,7 @@ if x is y: # O(1) - equivalent to id(x) == id(y)
10865
if x is not z: # O(1)
10966
print("Different objects")
11067

111-
# Avoid - using id() directly (less readable)
68+
# Avoid - using id() directly (less readable and slower)
11269
if id(x) == id(y):
11370
print("Same object")
11471
```
@@ -172,49 +129,6 @@ a['b'] = b # Create cycle
172129
print(has_cycle(a)) # True - cycle found
173130
```
174131

175-
## ID vs Equality
176-
177-
### Difference: == vs is
178-
179-
```python
180-
# == checks value equality
181-
x = [1, 2, 3]
182-
y = [1, 2, 3]
183-
print(x == y) # True - same content
184-
185-
# is checks object identity
186-
print(x is y) # False - different objects
187-
print(id(x) == id(y)) # False - equivalent
188-
189-
# For immutables, often same
190-
a = (1, 2, 3)
191-
b = (1, 2, 3)
192-
print(a == b) # True
193-
print(a is b) # Might be True or False (optimization)
194-
195-
# For None, always same object
196-
c = None
197-
d = None
198-
print(c is d) # Always True
199-
print(id(c) == id(d)) # Always True
200-
```
201-
202-
### Hashing and ID
203-
204-
```python
205-
# Hash and ID are different
206-
x = 42
207-
print(hash(x)) # Hash value - O(1)
208-
print(id(x)) # Object ID - O(1)
209-
210-
# Different objects can have same hash
211-
# But will have different IDs
212-
y = [1, 2, 3]
213-
z = [1, 2, 3]
214-
# hash(y) raises TypeError (unhashable)
215-
# But id(y) != id(z)
216-
```
217-
218132
## Implementation Details
219133

220134
### CPython: ID is Memory Address
@@ -281,68 +195,6 @@ cache[obj] = "data" # O(1) - cleaner
281195
value = cache[obj] # O(1)
282196
```
283197

284-
## Debugging and Inspection
285-
286-
### Object Tracking
287-
288-
```python
289-
# Use id() to track object creation - O(1)
290-
import sys
291-
292-
def track_objects():
293-
"""Show all objects and their IDs"""
294-
objects = {}
295-
296-
# Get all objects (memory intensive!)
297-
for obj in gc.get_objects(): # O(n)
298-
obj_id = id(obj) # O(1)
299-
obj_type = type(obj).__name__
300-
objects[obj_id] = obj_type
301-
302-
return objects
303-
304-
# Usage - useful for debugging memory issues
305-
# import gc
306-
# tracked = track_objects()
307-
```
308-
309-
### Identity and Memory
310-
311-
```python
312-
# id() shows object placement in memory
313-
x = "hello"
314-
y = "hello"
315-
z = x
316-
317-
print(id(x)) # Memory address 1
318-
print(id(y)) # Memory address 2 or 1 (interned)
319-
print(id(z)) # Memory address 1 (same as x)
320-
321-
# Shows that z and x are same object
322-
print(x is z) # True
323-
```
324-
325-
## Special Cases
326-
327-
### None and Booleans
328-
329-
```python
330-
# None is singleton - always same object
331-
a = None
332-
b = None
333-
print(id(a) == id(b)) # Always True
334-
print(a is b) # Always True
335-
336-
# Booleans are singletons
337-
true1 = True
338-
true2 = True
339-
print(id(true1) == id(true2)) # Always True
340-
341-
false1 = False
342-
false2 = False
343-
print(id(false1) == id(false2)) # Always True
344-
```
345-
346198
## Version Notes
347199

348200
- **Python 2.x**: id() available, returns memory address in CPython
@@ -362,12 +214,9 @@ print(id(false1) == id(false2)) # Always True
362214
- Use `is` operator instead of `id(x) == id(y)`
363215
- Use `is None` for None checks (standard)
364216
- Use id() for debugging and object tracking
365-
- Remember ID is implementation-dependent
366217

367218
**Avoid**:
368219

369220
- Using id() in regular code (use `is` instead)
370-
- Assuming specific ID values
371221
- Relying on ID across Python sessions
372222
- Using ID as hash for collections (use hash() or object itself)
373-
- Comparing IDs between different Python implementations

docs/builtins/locals_func.md

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -269,38 +269,19 @@ def slow_access(a, b, c):
269269
return locals()['a'] + locals()['b'] + locals()['c'] # Creates dict 3 times!
270270
```
271271

272-
## Best Practices
272+
## Related Functions
273273

274-
```python
275-
# ✅ DO: Use locals() for debugging/introspection
276-
def debug():
277-
x = 1
278-
y = 2
279-
print(locals()) # Good for understanding scope
280-
281-
# ✅ DO: Use it for variable existence checks
282-
if 'var_name' in locals():
283-
process(locals()['var_name'])
284-
285-
# ✅ DO: Understand it's a snapshot
286-
local_dict = locals()
287-
x = 10
288-
print('x' in local_dict) # False - dict is a snapshot
274+
- [globals() Function](globals.md) - Get global symbol table
275+
- [dir() Function](dir.md) - List accessible names
276+
- [vars() Function](vars.md) - Get __dict__ of object
289277

290-
# ❌ DON'T: Rely on modifications to locals()
291-
locals()['x'] = 20
292-
print(x) # Still old value (except in class body)
278+
## Best Practices
293279

294-
# ❌ DON'T: Use in tight loops for performance
295-
for i in range(1000000):
296-
v = locals()['var'] # Inefficient - creates dict each time
280+
**Do**:
297281

298-
# ❌ DON'T: Serialize/pickle locals() dict
299-
# It contains references that may not be picklable
300-
```
282+
- Use locals() for debugging/introspection
283+
- Use it for variable existence checks
301284

302-
## Related Functions
285+
**Avoid**:
303286

304-
- [globals() Function](globals.md) - Get global symbol table
305-
- [dir() Function](dir.md) - List accessible names
306-
- [vars() Function](vars.md) - Get __dict__ of object
287+
- Use in tight loops for performance

0 commit comments

Comments
 (0)