or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compilation.mddecorators.mdfunction-creation.mdindex.mdpartial.mdsignature-utils.mdwrapping.md

partial.mddocs/

0

# Partial Function Support

1

2

Enhanced partial function implementation with better introspection, documentation generation, and signature handling compared to `functools.partial`. These utilities provide superior user experience for partial function application with proper metadata preservation.

3

4

```python

5

from typing import Callable, Any, TypeVar

6

7

T = TypeVar('T')

8

```

9

10

## Capabilities

11

12

### Enhanced Partial Function

13

14

Improved version of `functools.partial` with better introspection and automatically generated documentation.

15

16

```python { .api }

17

def partial(f: Callable[..., T], *preset_pos_args: Any, **preset_kwargs: Any) -> Callable[..., T]:

18

"""

19

Enhanced functools.partial with better introspection and documentation.

20

21

Parameters:

22

- f: Callable[..., T], function to partially apply

23

- *preset_pos_args: Any, positional arguments to preset/bind

24

- **preset_kwargs: Any, keyword arguments to preset/bind

25

26

Returns:

27

Callable[..., T]: Partial function with enhanced metadata and signature

28

29

The returned function has:

30

- Proper signature reflecting remaining parameters

31

- Auto-generated docstring showing preset values

32

- .func attribute pointing to original function (like functools.partial)

33

- Better introspection support with inspect.signature()

34

35

Raises:

36

ValueError: If preset arguments don't match function signature

37

"""

38

```

39

40

### Partial Function Decorator

41

42

Decorator version of partial function for cleaner syntax when creating partial functions.

43

44

```python { .api }

45

def with_partial(*preset_pos_args: Any, **preset_kwargs: Any) -> Callable[[Callable[..., T]], Callable[..., T]]:

46

"""

47

Decorator to create partial function with preset arguments.

48

49

Parameters:

50

- *preset_pos_args: Any, positional arguments to preset

51

- **preset_kwargs: Any, keyword arguments to preset

52

53

Returns:

54

Callable[[Callable[..., T]], Callable[..., T]]: Decorator that creates partial function

55

"""

56

```

57

58

### Usage Examples

59

60

#### Basic Partial Function Creation

61

62

```python

63

from makefun import partial

64

from inspect import signature

65

66

def multiply(x: int, y: int, z: int = 1) -> int:

67

"""Multiply three numbers together."""

68

return x * y * z

69

70

# Create partial with first argument preset

71

double = partial(multiply, 2)

72

print(signature(double)) # (y: int, z: int = 1) -> int

73

print(double(5)) # 10 (2 * 5 * 1)

74

print(double(3, 4)) # 24 (2 * 3 * 4)

75

76

# Create partial with keyword argument preset

77

multiply_by_10 = partial(multiply, z=10)

78

print(signature(multiply_by_10)) # (x: int, y: int) -> int

79

print(multiply_by_10(2, 3)) # 60 (2 * 3 * 10)

80

```

81

82

#### Enhanced Documentation

83

84

```python

85

from makefun import partial

86

87

def api_request(method: str, url: str, headers: dict = None, timeout: int = 30) -> dict:

88

"""Make an HTTP API request."""

89

return {

90

"method": method,

91

"url": url,

92

"headers": headers or {},

93

"timeout": timeout

94

}

95

96

# Create partial for GET requests

97

get_request = partial(api_request, "GET", timeout=60)

98

99

# Automatic documentation generation

100

print(get_request.__doc__)

101

# <This function is equivalent to 'api_request('GET', url, headers=None, timeout=60)', see original 'api_request' doc below.>

102

# Make an HTTP API request.

103

104

print(get_request.__name__) # "api_request" (preserved from original)

105

```

106

107

#### Multiple Argument Presets

108

109

```python

110

from makefun import partial

111

112

def format_message(template: str, name: str, age: int, city: str = "Unknown") -> str:

113

"""Format a message with user information."""

114

return template.format(name=name, age=age, city=city)

115

116

# Preset template and city

117

welcome_message = partial(format_message, "Welcome {name}! You are {age} years old and live in {city}.", city="New York")

118

119

print(welcome_message("Alice", 25)) # Welcome Alice! You are 25 years old and live in New York.

120

print(welcome_message("Bob", 30, "Chicago")) # Welcome Bob! You are 30 years old and live in Chicago.

121

```

122

123

#### Decorator Syntax

124

125

```python

126

from makefun import with_partial

127

128

# Define base function

129

def compute_score(base: int, multiplier: float, bonus: int = 0) -> float:

130

"""Compute final score with base, multiplier, and bonus."""

131

return (base + bonus) * multiplier

132

133

# Create specialized versions using decorator

134

@with_partial(multiplier=1.5)

135

def boosted_score(base: int, bonus: int = 0) -> float:

136

pass # Implementation replaced by partial

137

138

@with_partial(multiplier=2.0, bonus=10)

139

def premium_score(base: int) -> float:

140

pass # Implementation replaced by partial

141

142

print(boosted_score(100)) # 150.0 (100 * 1.5)

143

print(boosted_score(100, 20)) # 180.0 ((100 + 20) * 1.5)

144

print(premium_score(100)) # 220.0 ((100 + 10) * 2.0)

145

```

146

147

#### Working with Complex Signatures

148

149

```python

150

from makefun import partial

151

from typing import List, Dict, Optional

152

153

def analyze_data(data: List[Dict], method: str, normalize: bool = True,

154

weights: Optional[Dict] = None, *extra_params, **options) -> Dict:

155

"""Analyze data using specified method with various options."""

156

result = {

157

"method": method,

158

"data_count": len(data),

159

"normalized": normalize,

160

"weights": weights,

161

"extra_params": extra_params,

162

"options": options

163

}

164

return result

165

166

# Create partial with method and normalization preset

167

statistical_analysis = partial(analyze_data, method="statistical", normalize=True)

168

169

# Remaining signature handles complex parameters correctly

170

sample_data = [{"value": 1}, {"value": 2}]

171

result = statistical_analysis(sample_data, weights={"a": 0.5}, "param1", "param2",

172

threshold=0.1, debug=True)

173

print(result)

174

```

175

176

#### Generator and Async Function Support

177

178

```python

179

from makefun import partial

180

import asyncio

181

182

def number_generator(start: int, end: int, step: int = 1, prefix: str = "Num"):

183

"""Generate numbers with optional prefix."""

184

for i in range(start, end, step):

185

yield f"{prefix}: {i}"

186

187

# Create partial generator

188

even_numbers = partial(number_generator, step=2, prefix="Even")

189

190

for num in even_numbers(0, 10):

191

print(num) # Even: 0, Even: 2, Even: 4, etc.

192

193

# Async function partial

194

async def fetch_data(url: str, method: str = "GET", timeout: int = 30) -> dict:

195

"""Simulate async data fetching."""

196

await asyncio.sleep(0.1)

197

return {"url": url, "method": method, "timeout": timeout}

198

199

# Create partial async function

200

quick_fetch = partial(fetch_data, timeout=5)

201

result = asyncio.run(quick_fetch("https://api.example.com", "POST"))

202

print(result)

203

```

204

205

#### Parameter Order and Keyword-Only Arguments

206

207

```python

208

from makefun import partial

209

210

def complex_func(a: int, b: str, c: float = 1.0, *, d: bool, e: str = "default") -> dict:

211

"""Function with positional and keyword-only parameters."""

212

return {"a": a, "b": b, "c": c, "d": d, "e": e}

213

214

# Preset keyword-only argument

215

simplified = partial(complex_func, d=True)

216

result = simplified(1, "hello", 2.5) # e uses default

217

print(result) # {"a": 1, "b": "hello", "c": 2.5, "d": True, "e": "default"}

218

219

# Preset positional and keyword arguments

220

more_simplified = partial(complex_func, 42, c=3.14, d=False, e="custom")

221

result2 = more_simplified("world")

222

print(result2) # {"a": 42, "b": "world", "c": 3.14, "d": False, "e": "custom"}

223

```

224

225

#### Error Handling

226

227

```python

228

from makefun import partial

229

230

def target_func(x: int, y: str) -> str:

231

return f"{x}: {y}"

232

233

# Invalid preset arguments

234

try:

235

invalid_partial = partial(target_func, 1, 2, 3) # Too many positional args

236

except ValueError as e:

237

print(f"Too many arguments: {e}")

238

239

try:

240

invalid_partial = partial(target_func, nonexistent_param="value") # Invalid keyword

241

except ValueError as e:

242

print(f"Invalid keyword: {e}")

243

```

244

245

### Comparison with functools.partial

246

247

Key advantages over `functools.partial`:

248

249

1. **Better Introspection**: Proper `inspect.signature()` support showing remaining parameters

250

2. **Enhanced Documentation**: Auto-generated docstrings showing preset values

251

3. **Signature Preservation**: Maintains proper type annotations and parameter information

252

4. **Better Error Messages**: Clear validation of preset arguments against function signature

253

254

```python

255

import functools

256

from makefun import partial

257

from inspect import signature

258

259

def example_func(x: int, y: str, z: float = 1.0) -> str:

260

"""Example function for comparison."""

261

return f"{x}, {y}, {z}"

262

263

# functools.partial

264

stdlib_partial = functools.partial(example_func, 42)

265

print(signature(stdlib_partial)) # (*args, **kwargs) - not helpful

266

267

# makefun.partial

268

enhanced_partial = partial(example_func, 42)

269

print(signature(enhanced_partial)) # (y: str, z: float = 1.0) -> str - precise!

270

271

print(stdlib_partial.__doc__) # partial(func, *args, **keywords) - generic

272

print(enhanced_partial.__doc__) # Shows actual preset values and original doc

273

```

274

275

### Integration with Other Makefun Features

276

277

Partial functions work seamlessly with other makefun utilities:

278

279

```python

280

from makefun import partial, wraps

281

282

def base_function(x: int, y: str, z: float = 1.0) -> str:

283

return f"Result: {x}, {y}, {z}"

284

285

# Create partial

286

preset_partial = partial(base_function, z=5.0)

287

288

# Wrap the partial with additional functionality

289

@wraps(preset_partial, prepend_args="verbose: bool = False")

290

def enhanced_partial(verbose, x, y):

291

if verbose:

292

print(f"Calling with x={x}, y={y}")

293

result = preset_partial(x, y)

294

if verbose:

295

print(f"Got: {result}")

296

return result

297

298

print(enhanced_partial(10, "test")) # Basic call

299

print(enhanced_partial(True, 20, "debug")) # Verbose call

300

```

301

302

### Function Attributes

303

304

Partial functions maintain compatibility with `functools.partial`:

305

306

```python

307

from makefun import partial

308

309

def original_func(a, b, c=1):

310

return a + b + c

311

312

# Create partial

313

p = partial(original_func, 10, c=5)

314

315

# Access original function

316

print(p.func) # Points to original_func

317

print(p.func(1, 2, 3)) # Can call original directly

318

319

# Check if it's a partial

320

import functools

321

print(isinstance(p, functools.partial)) # False - it's a generated function

322

print(hasattr(p, 'func')) # True - maintains .func attribute

323

```